前置知识: Python

面向对象编程

00:00
5 min Intermediate

类与对象、继承、多态、魔术方法与描述符。

1. 类与实例 (Class & Instance)

Python 是一门纯粹的面向对象语言,几乎所有的东西都是对象。

1.1 类的定义

 class Person:
  # 类属性 | Class attribute
  species = "Human"
  # 构造方法 | Constructor
  def __init__(self, name, age):
  self.name = name # 实例属性 | Instance attribute
  self.age = age
  # 实例方法 | Instance method
  def greet(self):
  return f"Hello, I am {self.name}"
 # 实例化
 p = Person("Alice", 30)
 print(p.name) # 输出: Alice
 print(p.age) # 输出: 30
 print(p.greet()) # 输出: Hello, I am Alice
 # 访问类属性
 print(Person.species) # 输出: Human
 print(p.species) # 输出: Human(实例也可以访问类属性)
 # 修改类属性
 Person.species = "Homo sapiens"
 print(Person.species) # 输出: Homo sapiens
 print(p.species) # 输出: Homo sapiens(实例的类属性也会改变)
 # 修改实例的类属性(只会影响该实例)
 p.species = "Human"
 print(Person.species) # 输出: Homo sapiens
 print(p.species) # 输出: Human

1.2 类的文档字符串

 class Person:
  """人类类"""
  def __init__(self, name, age):
  """初始化方法"""
  self.name = name
  self.age = age
  def greet(self):
  """打招呼方法"""
  return f"Hello, I am {self.name}"
 # 访问文档字符串
 print(Person.__doc__) # 输出: 人类类
 print(Person.__init__.__doc__) # 输出: 初始化方法
 print(Person.greet.__doc__) # 输出: 打招呼方法

2. 属性与方法 (Properties & Methods)

2.1 实例方法

实例方法是最常见的方法类型,它接收 self 作为第一个参数,指向当前实例。

 class Circle:
  def __init__(self, radius):
  self.radius = radius
  def area(self):
  """计算圆的面积"""
  return 3.14159 * self.radius ** 2
  def circumference(self):
  """计算圆的周长"""
  return 2 * 3.14159 * self.radius
 # 使用实例方法
 c = Circle(5)
 print(c.area()) # 输出: 78.53975
 print(c.circumference()) # 输出: 31.4159

2.2 类方法

类方法使用 @classmethod 装饰器,接收 cls 作为第一个参数,指向类本身。

 class Person:
  species = "Human"
  def __init__(self, name, age):
  self.name = name
  self.age = age
  @classmethod
  def get_species(cls):
  """获取物种信息"""
  return cls.species
  @classmethod
  def create_adult(cls, name):
  """创建一个成年人实例"""
  return cls(name, 18)
 # 使用类方法
 print(Person.get_species()) # 输出: Human
 # 使用类方法创建实例
 adult = Person.create_adult("Bob")
 print(adult.name) # 输出: Bob
 print(adult.age) # 输出: 18

2.3 静态方法

静态方法使用 @staticmethod 装饰器,不接收 selfcls 参数,是类的纯工具函数。

 class Math:
  @staticmethod
  def add(a, b):
  """加法运算"""
  return a + b
  @staticmethod
  def multiply(a, b):
  """乘法运算"""
  return a * b
 # 使用静态方法
 print(Math.add(2, 3)) # 输出: 5
 print(Math.multiply(2, 3)) # 输出: 6
 # 也可以通过实例调用静态方法
 m = Math()
 print(m.add(4, 5)) # 输出: 9

2.4 私有属性和方法

在 Python 中,使用双下划线 __ 开头的属性和方法被视为私有的,外部无法直接访问。

 class Person:
  def __init__(self, name, age):
  self.name = name # 公开属性
  self.__age = age # 私有属性
  def __private_method(self):
  """私有方法"""
  return f"This is a private method"
  def get_age(self):
  """获取年龄(通过公开方法访问私有属性)"""
  return self.__age
  def set_age(self, age):
  """设置年龄(通过公开方法修改私有属性)"""
  if age > 0:
  self.__age = age
 # 使用
 p = Person("Alice", 30)
 print(p.name) # 输出: Alice
 # print(p.__age) # 错误: 'Person' object has no attribute '__age'
 # print(p.__private_method()) # 错误: 'Person' object has no attribute '__private_method'
 # 通过公开方法访问私有属性
 print(p.get_age()) # 输出: 30
 p.set_age(31)
 print(p.get_age()) # 输出: 31
 # 注意: Python 实际上是通过名称修饰来实现私有性的
 # 可以通过 _ClassName__private 来访问私有属性(不推荐)
 print(p._Person__age) # 输出: 31
 print(p._Person__private_method()) # 输出: This is a private method

2.5 装饰器属性 (@property)

@property 装饰器可以将方法伪装成属性,使得可以像访问属性一样访问方法。

 class Person:
  def __init__(self, first_name, last_name):
  self.first_name = first_name
  self.last_name = last_name
  @property
  def full_name(self):
  """获取全名"""
  return f"{self.first_name} {self.last_name}"
  @full_name.setter
  def full_name(self, name):
  """设置全名"""
  first_name, last_name = name.split()
  self.first_name = first_name
  self.last_name = last_name
  @full_name.deleter
  def full_name(self):
  """删除全名"""
  self.first_name = None
  self.last_name = None
 # 使用属性装饰器
 p = Person("Alice", "Smith")
 print(p.full_name) # 输出: Alice Smith
 # 设置属性
 p.full_name = "Bob Johnson"
 print(p.first_name) # 输出: Bob
 print(p.last_name) # 输出: Johnson
 print(p.full_name) # 输出: Bob Johnson
 # 删除属性
 del p.full_name
 print(p.first_name) # 输出: None
 print(p.last_name) # 输出: None
 # print(p.full_name) # 输出: None None

3. 继承与多态 (Inheritance & Polymorphism)

3.1 单继承

 class Animal:
  def __init__(self, name):
  self.name = name
  def speak(self):
  return "Some generic sound"
 class Dog(Animal):
  def speak(self):
  return "Woof!"
 class Cat(Animal):
  def speak(self):
  return "Meow!"
 # 使用
 animal = Animal("Generic Animal")
 dog = Dog("Rex")
 cat = Cat("Whiskers")
 print(animal.speak()) # 输出: Some generic sound
 print(dog.speak()) # 输出: Woof!
 print(cat.speak()) # 输出: Meow!
 # 检查继承关系
 print(isinstance(dog, Animal)) # 输出:
 print(issubclass(Dog, Animal)) # 输出:

3.2 多继承

Python 支持多继承,一个子类可以继承多个父类。

 class A:
  def method(self):
  return "A.method()"
 class B:
  def method(self):
  return "B.method()"
  def other_method(self):
  return "B.other_method()"
 class C(A, B):
  pass
 # 使用
 c = C()
 print(c.method()) # 输出: A.method()(按照 MRO 顺序,先 A 后 B)
 print(c.other_method()) # 输出: B.other_method()
 # 查看方法解析顺序 (MRO)
 print(C.__mro__) # 输出: (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)

3.3 super() 函数

super() 函数用于调用父类的方法,在继承中非常有用。

 class Parent:
  def __init__(self, name):
  self.name = name
  def greet(self):
  return f"Hello from {self.name}"
 class Child(Parent):
  def __init__(self, name, age):
  super().__init__(name) # 调用父类的 __init__ 方法
  self.age = age
  def greet(self):
  parent_greeting = super().greet() # 调用父类的 greet 方法
  return f"{parent_greeting}, I'm {self.age} years old"
 # 使用
 child = Child("Bob", 10)
 print(child.greet()) # 输出: Hello from Bob, I'm 10 years old

3.4 多态

多态是指不同类型的对象可以使用相同的接口。

 def make_speak(animal):
  """让动物发声"""
  print(animal.speak())
 # 使用
 make_speak(Dog("Rex")) # 输出: Woof!
 make_speak(Cat("Whiskers")) # 输出: Meow!
 make_speak(Animal("Generic")) # 输出: Some generic sound

3.5 鸭子类型

Python 采用鸭子类型,不关注对象的具体类型,只关注对象是否具有所需的方法或属性。

 class Duck:
  def quack(self):
  return "Quack!"
 class Person:
  def quack(self):
  return "I'm quacking like a duck!"
 def make_quack(obj):
  """让对象发出鸭叫声"""
  if hasattr(obj, 'quack'):
  print(obj.quack())
  else:
  print("This object can't quack")
 # 使用
 make_quack(Duck()) # 输出: Quack!
 make_quack(Person()) # 输出: I'm quacking like a duck!

4. 特殊方法 (Magic Methods)

特殊方法(也称为魔术方法或双下划线方法)是 Python 中具有特殊功能的方法,它们以双下划线开头和结尾。

4.1 基本特殊方法

 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})"
  def __repr__(self):
  """字符串表示(对开发者友好)"""
  return f"Person('{self.name}', {self.age})"
  def __eq__(self, other):
  """相等性比较"""
  if not isinstance(other, Person):
  return NotImplemented
  return self.name == other.name and self.age == other.age
  def __lt__(self, other):
  """小于比较"""
  if not isinstance(other, Person):
  return NotImplemented
  return self.age < other.age
 # 使用
 p1 = Person("Alice", 30)
 p2 = Person("Bob", 25)
 p3 = Person("Alice", 30)
 print(str(p1)) # 输出: Person(name='Alice', age=30)
 print(repr(p1)) # 输出: Person('Alice', 30)
 print(p1 == p2) # 输出: False
 print(p1 == p3) # 输出:
 print(p1 < p2) # 输出: False
 print(p2 < p1) # 输出:

4.2 容器相关的特殊方法

 class MyList:
  def __init__(self, items):
  self.items = items
  def __len__(self):
  """获取长度"""
  return len(self.items)
  def __getitem__(self, index):
  """获取元素"""
  return self.items[index]
  def __setitem__(self, index, value):
  """设置元素"""
  self.items[index] = value
  def __contains__(self, item):
  """检查元素是否存在"""
  return item in self.items
 # 使用
 my_list = MyList([1, 2, 3, 4, 5])
 print(len(my_list)) # 输出: 5
 print(my_list[0]) # 输出: 1
 my_list[0] = 10
 print(my_list[0]) # 输出: 10
 print(3 in my_list) # 输出:
 print(100 in my_list) # 输出: False
 # 支持迭代
 for item in my_list:
  print(item, end=" ") # 输出: 10 2 3 4 5

4.3 算术运算符特殊方法

 class Vector:
  def __init__(self, x, y):
  self.x = x
  self.y = y
  def __add__(self, other):
  """加法运算"""
  if not isinstance(other, Vector):
  return NotImplemented
  return Vector(self.x + other.x, self.y + other.y)
  def __sub__(self, other):
  """减法运算"""
  if not isinstance(other, Vector):
  return NotImplemented
  return Vector(self.x - other.x, self.y - other.y)
  def __mul__(self, scalar):
  """乘法运算"""
  return Vector(self.x * scalar, self.y * scalar)
  def __str__(self):
  return f"Vector({self.x}, {self.y})"
 # 使用
 v1 = Vector(1, 2)
 v2 = Vector(3, 4)
 print(v1 + v2) # 输出: Vector(4, 6)
 print(v1 - v2) # 输出: Vector(-2, -2)
 print(v1 * 2) # 输出: Vector(2, 4)

5. 高级面向对象特性

5.1 抽象基类

抽象基类(Abstract Base Class, ABC)用于定义接口,强制子类实现特定的方法。

 from abc import ABC, abstractmethod
 class Animal(ABC):
  @abstractmethod
  def speak(self):
  """动物发声"""
  pass
  @abstractmethod
  def move(self):
  """动物移动"""
  pass
 class Dog(Animal):
  def speak(self):
  return "Woof!"
  def move(self):
  return "Running"
 class Cat(Animal):
  def speak(self):
  return "Meow!"
  def move(self):
  return "Walking"
 # 使用
 dog = Dog()
 print(dog.speak()) # 输出: Woof!
 print(dog.move()) # 输出: Running
 cat = Cat()
 print(cat.speak()) # 输出: Meow!
 print(cat.move()) # 输出: Walking
 # 不能实例化抽象基类
 # animal = Animal() # 错误: Can't instantiate abstract class Animal with abstract methods move, speak

5.2 混入类 (Mixins)

混入类是一种特殊的类,用于为其他类提供功能,而不是作为独立的类使用。

 class SwimMixin:
  def swim(self):
  return "Swimming"
 class FlyMixin:
  def fly(self):
  return "Flying"
 class Duck(SwimMixin, FlyMixin):
  def quack(self):
  return "Quack!"
 class Penguin(SwimMixin):
  def walk(self):
  return "Walking"
 # 使用
 duck = Duck()
 print(duck.quack()) # 输出: Quack!
 print(duck.swim()) # 输出: Swimming
 print(duck.fly()) # 输出: Flying
 penguin = Penguin()
 print(penguin.swim()) # 输出: Swimming
 print(penguin.walk()) # 输出: Walking
 # print(penguin.fly()) # 错误: 'Penguin' object has no attribute 'fly'

5.3 单例模式

单例模式确保一个类只有一个实例。

 class Singleton:
  _instance = None
  def __new__(cls, *args, **kwargs):
  if not cls._instance:
  cls._instance = super().__new__(cls)
  return cls._instance
  def __init__(self, value=None):
  if value is not None:
  self.value = value
 # 使用
 s1 = Singleton("First")
 print(s1.value) # 输出: First
 # 第二次创建会返回同一个实例
 s2 = Singleton("Second")
 print(s2.value) # 输出: Second
 print(s1 is s2) # 输出:
 print(s1.value) # 输出: Second(因为 s1 和 s2 是同一个实例)

5.4 类装饰器

类装饰器用于修改类的行为。

 def debug(cls):
  """类装饰器:为类的所有方法添加调试信息"""
  for name, method in list(cls.__dict__.items()):
  if callable(method) and not name.startswith('__'):
  def wrapper(*args, **kwargs):
  print(f"Calling {name} with args: {args}, kwargs: {kwargs}")
  result = method(*args, **kwargs)
  print(f"{name} returned: {result}")
  return result
  setattr(cls, name, wrapper)
  return cls
 @debug
 class Calculator:
  def add(self, a, b):
  return a + b
  def multiply(self, a, b):
  return a * b
 # 使用
 calc = Calculator()
 calc.add(2, 3) # 输出: Calling add with args: (<__main__.Calculator object at 0x...>, 2, 3), kwargs: {}
  # add returned: 5
 calc.multiply(4, 5) # 输出: Calling multiply with args: (<__main__.Calculator object at 0x...>, 4, 5), kwargs: {}
  # multiply returned: 20

6. 面向对象编程的最佳实践

6.1 设计原则

  • 单一职责原则: 一个类应该只有一个引起它变化的原因
  • 开放-封闭原则: 对扩展开放,对修改封闭
  • 里氏替换原则: 子类应该能够替换父类
  • 依赖倒置原则: 依赖于抽象,而不是具体实现
  • 接口隔离原则: 客户端不应该依赖它不需要的接口

6.2 代码风格

  • 命名约定: 类名使用驼峰命名法(如 MyClass),方法和属性使用蛇形命名法(如 my_method
  • 文档: 为方法属性添加文档字符串
  • 缩进: 使用 4 个空缩进
  • : 每代码不超过 79 个字符
  • 导入: 按标准库、第三方本地的顺序导入

6.3 常见陷阱

  • 可变默认参数: 避免使用可变对象作为默认参数
  • 循环引用: 注意避免循环引用导致的内存泄漏
  • 继承: 避免深层继承层次结构
  • 使用继承: 考虑使用组合而不是继承
  • 魔法方法滥用: 只在必要时使用魔法方法

7. 实际应用示例

7.1 学生管理系统

 class Student:
  def __init__(self, id, name, age, grade):
  self.id = id
  self.name = name
  self.age = age
  self.grade = grade
  def __str__(self):
  return f"Student(id={self.id}, name='{self.name}', age={self.age}, grade={self.grade})"
 class StudentManager:
  def __init__(self):
  self.students = []
  def add_student(self, student):
  """添加学生"""
  self.students.append(student)
  def remove_student(self, student_id):
  """移除学生"""
  self.students = [s for s in self.students if s.id != student_id]
  def get_student(self, student_id):
  """获取学生"""
  for student in self.students:
  if student.id == student_id:
  return student
  return None
  def get_all_students(self):
  """获取所有学生"""
  return self.students
 # 使用
 manager = StudentManager()
 # 添加学生
 manager.add_student(Student(1, "Alice", 18, 90))
 manager.add_student(Student(2, "Bob", 17, 85))
 manager.add_student(Student(3, "Charlie", 19, 95))
 # 获取所有学生
 for student in manager.get_all_students():
  print(student)
 # 获取特定学生
 student = manager.get_student(2)
 print(f"Found student: {student}")
 # 移除学生
 manager.remove_student(2)
 print("After removing student 2:")
 for student in manager.get_all_students():
  print(student)

7.2 形状计算

 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)
 class Circle(Shape):
  def __init__(self, radius):
  self.radius = radius
  def area(self):
  return 3.14159 * self.radius ** 2
  def perimeter(self):
  return 2 * 3.14159 * self.radius
 class Triangle(Shape):
  def __init__(self, a, b, c):
  self.a = a
  self.b = b
  self.c = c
  def area(self):
  # 使用海伦公式计算面积
  s = (self.a + self.b + self.c) / 2
  return (s * (s - self.a) * (s - self.b) * (s - self.c)) ** 0.5
  def perimeter(self):
  return self.a + self.b + self.c
 # 使用
 shapes = [
  Rectangle(5, 4),
  Circle(3),
  Triangle(3, 4, 5)
 ]
 for shape in shapes:
  print(f"{type(shape).__name__}: Area = {shape.area():.2f}, Perimeter = {shape.perimeter():.2f}")

更新日志 (Changelog)

  • 2026-04-05: 体系化整合 Python 对象基础与特殊方法
  • 2026-04-05: 扩写内容增加详细的实例属性方法继承多态特殊方法对象特性和实际示例等内容

知识检测

学习进度

-- 已学文档
--% 知识覆盖率

学习推荐

专注模式