面向对象编程
类与对象、继承、多态、魔术方法与描述符。
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 装饰器,不接收 self 或 cls 参数,是类的纯工具函数。
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: 扩写内容,增加详细的类与实例、属性与方法、继承与多态、特殊方法、高级面向对象特性和实际示例等内容。