mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
133 字
1 分钟
Python 面向对象与设计模式
2024-07-17

一、类变量与实例变量#

1.1 核心区别#

class Dog:
kind = "dog" # 类变量:所有实例共享
def __init__(self, name):
self.name = name # 实例变量:每个实例独立
d1 = Dog("旺财")
d2 = Dog("小白")
print(d1.kind) # dog - 通过实例查找
print(d2.kind) # dog
print(Dog.kind) # dog - 通过类访问
d1.kind = "big dog" # 创建实例变量,不影响类
print(d1.kind) # big dog (实例变量)
print(d2.kind) # dog (类变量)
print(Dog.kind) # dog (类变量不变)

1.2 可变对象陷阱#

# 可变对象作为类变量的危险
class Registry:
items = [] # 所有实例共享同一个列表!
r1 = Registry()
r2 = Registry()
r1.items.append("item1")
print(r2.items) # ['item1'] - 意外共享!
# 正确做法:使用实例变量
class RegistryFixed:
def __init__(self):
self.items = [] # 每个实例独立列表
def add(self, item):
self.items.append(item)
r1 = RegistryFixed()
r2 = RegistryFixed()
r1.items.append("item1")
print(r2.items) # [] - 独立列表

1.3 property 装饰器#

class Circle:
def __init__(self, radius):
self._radius = radius # 私有属性
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value < 0:
raise ValueError("半径不能为负数")
self._radius = value
@property
def area(self):
return 3.14159 * self._radius ** 2
c = Circle(5)
print(c.radius) # 5
print(c.area) # 78.53975
c.radius = 10
print(c.area) # 314.159

二、继承与 MRO#

2.1 方法解析顺序#

class A:
def method(self):
return "A"
class B(A):
def method(self):
return "B"
class C(A):
def method(self):
return "C"
class D(B, C):
pass
d = D()
print(d.method()) # "B" - 按 MRO 顺序优先使用 B
# 查看 MRO
print(D.__mro__)
# (<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>)

2.2 super() 的工作原理#

class Base:
def __init__(self):
print("Base init")
class Child(Base):
def __init__(self):
super().__init__() # 调用父类
print("Child init")
# super() 沿着 MRO 顺序查找
class A:
def method(self):
print("A")
class B(A):
def method(self):
super().method()
print("B")
class C(A):
def method(self):
super().method()
print("C")
class D(B, C):
def method(self):
super().method()
print("D")
D().method()
# 输出: A C B D
# MRO: D -> B -> C -> A

2.3 多继承的菱形问题#

# 菱形继承
class Base:
def method(self):
print("Base")
class Left(Base):
pass
class Right(Base):
def method(self):
print("Right")
class Child(Left, Right):
pass
Child().method() # 无输出!Left 优先于 Right
# Python 3 使用 C3 线性化算法
# MRO: Child -> Left -> Right -> Base -> object
# 明确调用
class Child(Left, Right):
def method(self):
super().method() # 调用 Left,然后 Right,然后 Base

三、常见设计模式#

3.1 单例模式#

# 方式1: __new__ 方法
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
# 方式2: 装饰器
def singleton(cls):
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class Database:
pass
# 方式3: 元类
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class Database(metaclass=SingletonMeta):
pass
# 方式4: 模块级单例(最简单)
# mysingleton.py
class _MySingleton:
pass
singleton = _MySingleton()

3.2 工厂模式#

# 简单工厂
class Dog:
def speak(self): return "汪汪"
class Cat:
def speak(self): return "喵喵"
class Factory:
@staticmethod
def create(animal_type):
animals = {"dog": Dog, "cat": Cat}
return animals[animal_type]()
factory = Factory()
animal = factory.create("dog")
print(animal.speak()) # 汪汪
# 工厂方法模式
class Animal:
def speak(self): raise NotImplementedError
class AnimalFactory:
def create(self): raise NotImplementedError
class DogFactory(AnimalFactory):
def create(self): return Dog()
# 抽象工厂
class AbstractFactory:
def create_product_a(self): pass
def create_product_b(self): pass

3.3 观察者模式#

class Subject:
def __init__(self):
self._observers = []
def attach(self, observer):
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self, message):
for observer in self._observers:
observer.update(message)
class Observer:
def update(self, message):
print(f"收到通知: {message}")
subject = Subject()
observer = Observer()
subject.attach(observer)
subject.notify("Hello") # 收到通知: Hello

3.4 策略模式#

class SortStrategy:
def sort(self, data): raise NotImplementedError
class QuickSort(SortStrategy):
def sort(self, data):
return sorted(data)
class MergeSort(SortStrategy):
def sort(self, data):
return sorted(data, reverse=True)
class Context:
def __init__(self, strategy):
self.strategy = strategy
def execute(self, data):
return self.strategy.sort(data)
context = Context(QuickSort())
print(context.execute([3, 1, 2])) # [1, 2, 3]

3.5 装饰器模式#

# 组合优于继承
class Component:
def operation(self): return "原始"
class Decorator(Component):
def __init__(self, wrapped):
self._wrapped = wrapped
def operation(self):
return f"装饰({self._wrapped.operation()})"
component = Component()
decorated = Decorator(component)
print(decorated.operation()) # 装饰(原始)

3.6 迭代器模式#

class TreeNode:
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
class Tree:
def __init__(self, root):
self.root = root
def __iter__(self):
# 中序遍历
def inorder(node):
if node is None:
return
yield from inorder(node.left)
yield node.value
yield from inorder(node.right)
yield from inorder(self.root)
# 使用
root = TreeNode(1, TreeNode(2), TreeNode(3))
tree = Tree(root)
for value in tree:
print(value) # 2, 1, 3

四、魔术方法#

4.1 常用魔术方法#

class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
# 字符串表示
def __repr__(self): return f"Vector({self.x}, {self.y})"
def __str__(self): return f"({self.x}, {self.y})"
# 比较运算符
def __eq__(self, other): return self.x == other.x and self.y == other.y
def __lt__(self, other): return self.x < other.x or (self.x == other.x and self.y < other.y)
# 算术运算符
def __add__(self, other): return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other): return Vector(self.x - other.x, self.y - other.y)
def __mul__(self, scalar): return Vector(self.x * scalar, self.y * scalar)
# 可调用
def __call__(self): return f"Vector({self.x}, {self.y})"
# 长度
def __len__(self): return 2
# 索引访问
def __getitem__(self, index):
if index == 0: return self.x
if index == 1: return self.y
raise IndexError

4.2 容器协议#

class CustomList:
def __init__(self, items):
self.items = items
def __len__(self): return len(self.items)
def __getitem__(self, i): return self.items[i]
def __setitem__(self, i, v): self.items[i] = v
def __contains__(self, v): return v in self.items
def __iter__(self): return iter(self.items)
def __add__(self, other): return CustomList(self.items + other.items)

五、接口与抽象基类#

5.1 抽象基类#

from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self): pass
@abstractmethod
def perimeter(self): pass
def display(self):
print(f"Area: {self.area()}")
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self): return self.width * self.height
def perimeter(self): return 2 * (self.width + self.height)
# 不能实例化抽象类
# shape = Shape() # TypeError
rect = Rectangle(5, 3)
rect.display() # Area: 15

5.2 Protocol (Python 3.8+)#

from typing import Protocol
class Drawable(Protocol):
def draw(self) -> None: ...
class Circle:
def draw(self) -> None:
print("Drawing circle")
def render(d: Drawable) -> None:
d.draw()
render(Circle()) # 有效,Circle 实现了 draw 方法

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

Python 面向对象与设计模式
https://blog.souloss.com/posts/interview/python-oop/
作者
Souloss
发布于
2024-07-17
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时