Skip to content

1. 类和对象

1-1. 类定义

Python 中,类通过 class 关键字定义。类名通常使用大写字母开头。

python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

TIP

__init__ 方法是一个特殊的构造方法,用于初始化对象的属性。

1-2. 对象创建

python
person = Person("John", 25)
print(person.name)  # 输出: John
print(person.age)   # 输出: 25

1-3. 继承

Python 中,继承通过在类定义时指定父类来实现。

python
class Student(Person):
    def __init__(self, name, age, student_id):
        super().__init__(name, age)
        self.student_id = student_id

TIP

super() 函数用于调用父类的方法。

1-4. 多态

多态是指同一个方法在不同的子类中具有不同的实现。

python
class Animal:
    def speak(self):
        pass
python
class Dog(Animal):
    def speak(self):
        return "Woof"
python
animal = Animal()
dog = Dog()

print(animal.speak())  # 输出: None
print(dog.speak())    # 输出: Woof

TIP

多态使得代码更加灵活和可扩展。

1-5. 封装

封装是将数据和操作数据的方法绑定在一起,隐藏对象的内部实现细节。

python
class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self.__balance = balance  # 私有属性

    def deposit(self, amount):
        self.__balance += amount

    def get_balance(self):
        return self.__balance

TIP

私有属性不能直接访问,需要通过类提供的方法来访问。

1-6. 抽象类和接口

  1. 抽象类
python
from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

    @abstractmethod
    def perimeter(self):
        pass

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)
  1. 接口(Protocol)
python
from typing import Protocol

class Drawable(Protocol):
    def draw(self) -> str:
        ...

class Circle:
    def draw(self) -> str:
        return "绘制圆形"

class Square:
    def draw(self) -> str:
        return "绘制方形"

1-7. 多重继承

python
class A:
    def method_a(self):
        return "A"

class B:
    def method_b(self):
        return "B"

class C(A, B):
    def method_c(self):
        return "C"

c = C()
print(c.method_a())  # A
print(c.method_b())  # B
print(c.method_c())  # C

TIP

多重继承可能导致菱形继承问题,需要注意方法解析顺序(MRO)。

1-8. 组合和聚合

  1. 组合
python
class Engine:
    def start(self):
        return "引擎启动"

class Car:
    def __init__(self):
        self.engine = Engine()  # 组合关系

    def start(self):
        return self.engine.start()

car = Car()
print(car.start())  # 引擎启动
  1. 聚合
python
class Department:
    def __init__(self, name):
        self.name = name
        self.employees = []  # 聚合关系

    def add_employee(self, employee):
        self.employees.append(employee)

class Employee:
    def __init__(self, name):
        self.name = name

dept = Department("技术部")
emp1 = Employee("张三")
emp2 = Employee("李四")
dept.add_employee(emp1)
dept.add_employee(emp2)

2. 魔术方法

魔术方法(Magic Methods)是 Python 中的一些特殊方法,它们在类中定义,用于实现一些特殊的行为。以下是一些常用的魔术方法:

2-1. __str__

__str__ 方法用于定义对象的 str 方法。

python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return f"Person(name={self.name}, age={self.age})"
python
person = Person("John", 25)
print(person)  # 输出: Person(name=John, age=25)

2-2. __repr__

__repr__ 方法用于定义对象的 repr 方法。

python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return f"Person(name={self.name}, age={self.age})"
python
person = Person("John", 25)
print(repr(person))  # 输出: Person(name=John, age=25)

2-3. __len__

__len__ 方法用于定义对象的 len 方法。

python
class MyList:
    def __init__(self, items):
        self.items = items

    def __len__(self):
        return len(self.items)
python
my_list = MyList([1, 2, 3, 4, 5])
print(len(my_list))  # 输出: 5

2-4. __getitem__

__getitem__ 方法用于定义对象的 getitem 方法。

python
class MyList:
    def __init__(self, items):
        self.items = items

    def __getitem__(self, index):
        return self.items[index]
python
my_list = MyList([1, 2, 3, 4, 5])
print(my_list[0])  # 输出: 1

2-5. __setitem__

__setitem__ 方法用于定义对象的 setitem 方法。

python
class MyList:
    def __init__(self, items):
        self.items = items

    def __setitem__(self, index, value):
        self.items[index] = value
python
my_list = MyList([1, 2, 3, 4, 5])
my_list[0] = 10  # 输出: [10, 2, 3, 4, 5]

2-6. __delitem__

__delitem__ 方法用于定义对象的 delitem 方法。

python
class MyList:
    def __init__(self, items):
        self.items = items

    def __delitem__(self, index):
        del self.items[index]
python
my_list = MyList([1, 2, 3, 4, 5])
del my_list[0]  # 输出: [2, 3, 4, 5]

2-7. __call__

__call__ 方法用于定义对象的 call 方法。

python
class MyClass:
    def __call__(self, *args, **kwargs):
        return "Hello, World!"
python
my_class = MyClass()
print(my_class())  # 输出: Hello, World!

2-8. __iter__

__iter__ 方法用于定义对象的 iter 方法。

python
class MyIterable:
    def __iter__(self):
        return iter([1, 2, 3])
python
my_iterable = MyIterable()
for item in my_iterable:
    print(item)  # 输出: 1 2 3

2-9. __next__

__next__ 方法用于定义对象的 next 方法。

python
class MyIterator:
    def __init__(self, data):
        self.data = data
        self.index = 0

    def __next__(self):
        if self.index < len(self.data):
            result = self.data[self.index]
            self.index += 1
            return result
        else: 
            raise StopIteration
python
my_iterator = MyIterator([1, 2, 3])
print(next(my_iterator))  # 输出: 1

2-10. __contains__

__contains__ 方法用于定义对象的 contains 方法。

python
class MyContainer:
    def __contains__(self, item):
        return item in [1, 2, 3]
python
print(2 in my_container)  # 输出: True

2-11. __getattr__

__getattr__ 方法用于定义对象的 getattr 方法。

python
class MyClass:
    def __getattr__(self, name):
        return f"Attribute '{name}' not found"
python
my_class = MyClass()
print(my_class.name)  # 输出: Attribute 'name' not found

2-12. __setattr__

__setattr__ 方法用于定义对象的 setattr 方法。

python
class MyClass:
    def __setattr__(self, name, value):
        self.__dict__[name] = value
python
my_class = MyClass()
my_class.name = "John"
print(my_class.name)  # 输出: John

2-13. __getattribute__

__getattribute__ 方法用于定义对象的 getattribute 方法。

python
class MyClass:
    def __getattribute__(self, name):
        return f"Attribute '{name}' not found"
python
my_class = MyClass()
print(my_class.name)  # 输出: Attribute 'name' not found

2-14. __setattribute__

__setattribute__ 方法用于定义对象的 setattribute 方法。

python
class MyClass:
    def __setattribute__(self, name, value):
        self.__dict__[name] = value
python
my_class = MyClass()
my_class.name = "John"
print(my_class.name)  # 输出: John

2-15. __delattr__

__delattr__ 方法用于定义对象的 delattr 方法。

python
class MyClass:
    def __delattr__(self, name):
        del self.__dict__[name]
python
my_class = MyClass()
my_class.name = "John"
del my_class.name  # 输出: Attribute 'name' not found

3. 属性装饰器

3-1. @property 装饰器

@property 装饰器用于将方法转换为只读属性,它有以下主要用途:

  1. 数据验证和转换
python
class Person:
    def __init__(self, age):
        self._age = age

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if not isinstance(value, int):
            raise TypeError("年龄必须是整数")
        if value < 0 or value > 150:
            raise ValueError("年龄必须在0-150之间")
        self._age = value

person = Person(25)
print(person.age)  # 25
person.age = 30    # 正常赋值
person.age = -1    # 抛出 ValueError
  1. 计算属性
python
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    @property
    def area(self):
        return self.width * self.height

    @property
    def perimeter(self):
        return 2 * (self.width + self.height)

rect = Rectangle(5, 3)
print(rect.area)      # 15
print(rect.perimeter) # 16
  1. 只读属性
python
class Circle:
    def __init__(self, radius):
        self._radius = radius

    @property
    def radius(self):
        return self._radius

    @property
    def diameter(self):
        return self._radius * 2

circle = Circle(5)
print(circle.radius)    # 5
print(circle.diameter)  # 10
# circle.radius = 10    # 错误:只读属性

3-2. 类属性的其他定义方式

  1. 类变量
python
class Student:
    # 类变量,所有实例共享
    school = "Python大学"
    
    def __init__(self, name):
        # 实例变量
        self.name = name

student1 = Student("张三")
student2 = Student("李四")
print(student1.school)  # Python大学
print(student2.school)  # Python大学
Student.school = "新Python大学"  # 修改类变量
print(student1.school)  # 新Python大学
  1. 描述符(Descriptor)
python
class Age:
    def __get__(self, instance, owner):
        return instance._age

    def __set__(self, instance, value):
        if not isinstance(value, int):
            raise TypeError("年龄必须是整数")
        if value < 0 or value > 150:
            raise ValueError("年龄必须在0-150之间")
        instance._age = value

class Person:
    age = Age()  # 使用描述符

    def __init__(self, age):
        self._age = age

person = Person(25)
print(person.age)  # 25
person.age = 30    # 正常赋值
# person.age = -1  # 抛出 ValueError
  1. __slots__ 类属性
python
class Point:
    __slots__ = ['x', 'y']  # 限制实例只能有 x 和 y 属性

    def __init__(self, x, y):
        self.x = x
        self.y = y

point = Point(1, 2)
# point.z = 3  # 错误:无法添加新属性
  1. __dict__ 和动态属性
python
class DynamicClass:
    def __init__(self):
        self.__dict__['dynamic_attr'] = 'value'

    def __getattr__(self, name):
        if name == 'missing_attr':
            return '动态属性值'
        raise AttributeError(f"属性 {name} 不存在")

    def __setattr__(self, name, value):
        if name.startswith('_'):
            raise AttributeError("不能设置以下划线开头的属性")
        super().__setattr__(name, value)

obj = DynamicClass()
print(obj.dynamic_attr)  # value
print(obj.missing_attr)  # 动态属性值
# obj._private = 1      # 错误:不能设置以下划线开头的属性
  1. 元类(Metaclass)定义类属性
python
class Meta(type):
    def __new__(cls, name, bases, attrs):
        # 添加类属性
        attrs['version'] = '1.0'
        attrs['author'] = 'Python'
        return super().__new__(cls, name, bases, attrs)

class MyClass(metaclass=Meta):
    pass

print(MyClass.version)  # 1.0
print(MyClass.author)   # Python

3-3. 属性访问控制

  1. 私有属性
python
class BankAccount:
    def __init__(self, balance):
        self.__balance = balance  # 私有属性

    def get_balance(self):
        return self.__balance

    def set_balance(self, value):
        if value >= 0:
            self.__balance = value

account = BankAccount(1000)
print(account.get_balance())  # 1000
# print(account.__balance)    # 错误:无法直接访问私有属性
  1. 保护属性
python
class Parent:
    def __init__(self):
        self._protected = "受保护的属性"  # 保护属性

class Child(Parent):
    def access_protected(self):
        return self._protected  # 子类可以访问

child = Child()
print(child.access_protected())  # 受保护的属性
# print(child._protected)        # 可以访问,但不推荐

3-4. 属性装饰器的使用场景

  1. 数据验证和转换

    • 输入验证
    • 数据格式转换
    • 范围检查
  2. 计算属性

    • 基于其他属性计算
    • 缓存计算结果
    • 延迟计算
  3. 只读属性

    • 防止属性被修改
    • 封装内部实现
    • 提供只读接口
  4. 属性依赖

    • 属性之间的关联
    • 自动更新相关属性
    • 维护数据一致性
  5. 接口兼容

    • 保持向后兼容
    • 重构内部实现
    • 提供统一接口

4. 类装饰器

4-1. 类方法装饰器

python
class MyClass:
    @classmethod
    def create(cls, value):
        return cls(value)

    def __init__(self, value):
        self.value = value

obj = MyClass.create(10)
print(obj.value)  # 10

4-2. 静态方法装饰器

python
class Math:
    @staticmethod
    def add(x, y):
        return x + y

    @staticmethod
    def multiply(x, y):
        return x * y

print(Math.add(5, 3))      # 8
print(Math.multiply(5, 3)) # 15

4-3. 抽象方法装饰器

python
from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

    @abstractmethod
    def perimeter(self):
        pass

5. 设计模式

5-1. 单例模式

python
class Singleton:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

s1 = Singleton()
s2 = Singleton()
print(s1 is s2)  # True

5-2. 工厂模式

python
class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "Woof"

class Cat(Animal):
    def speak(self):
        return "Meow"

class AnimalFactory:
    @staticmethod
    def create_animal(animal_type):
        if animal_type == "dog":
            return Dog()
        elif animal_type == "cat":
            return Cat()
        else:
            raise ValueError("未知的动物类型")

dog = AnimalFactory.create_animal("dog")
cat = AnimalFactory.create_animal("cat")
print(dog.speak())  # Woof
print(cat.speak())  # Meow

5-3. 观察者模式

python
class Subject:
    def __init__(self):
        self.observers = []

    def attach(self, observer):
        self.observers.append(observer)

    def notify(self):
        for observer in self.observers:
            observer.update()

class Observer:
    def update(self):
        pass

class ConcreteObserver(Observer):
    def update(self):
        print("收到通知")

subject = Subject()
observer = ConcreteObserver()
subject.attach(observer)
subject.notify()  # 收到通知