Python 面向对象
面向对象编程(OOP)以「对象」为核心组织代码——将数据和处理数据的函数封装为独立模块。Python 从设计之初就是一门面向对象语言。
基本概念
OOP 三个核心特点:
- 封装:将状态(数据)和行为(方法)包装在一起,隐藏内部实现,对外暴露接口
- 继承:子类复用父类属性和方法,实现代码复用和层次化设计
- 多态:不同类的对象对同一消息做出不同响应,提供统一接口
类与对象
定义类
class Dog:
species = "Canis familiaris" # 类属性——所有实例共享
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age
def bark(self): # 实例方法
return f"{self.name} says woof!"创建实例
my_dog = Dog("Rex", 3)
print(my_dog.name) # Rex
print(my_dog.species) # Canis familiaris
print(my_dog.bark()) # Rex says woof!__init__
构造函数,创建实例时自动调用。self 代表实例本身:
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age封装
通过私有属性和方法隐藏实现细节。
class Dog:
def __init__(self, name):
self.__name = name # 双下划线 → 私有
def __bark(self): # 私有方法
return f"{self.__name} says woof!"
def public_bark(self): # 公共接口
return self.__bark()使用 @property 提供受控访问(见下文 property 章节)。
继承
单继承
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal): # Dog 继承 Animal
def bark(self):
return f"{self.name} says woof!"多继承
Python 支持多继承,但需注意菱形问题(MRO 解决):
class Swimming:
def swim(self):
return "Swims!"
class Flying:
def fly(self):
return "Flies!"
class Duck(Swimming, Flying):
pass
duck = Duck()
duck.swim() # Swims!
duck.fly() # Flies!super()
调用父类方法:
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # 调用父类构造函数
self.breed = breed多态
方法重写
class Animal:
def sound(self):
return "Some sound"
class Dog(Animal):
def sound(self):
return "Woof!" # 重写
class Cat(Animal):
def sound(self):
return "Meow!" # 重写Duck Typing
Python 是动态类型——不关心对象”是什么”,只关心”能做什么”:
def animal_sound(animal):
return animal.sound() # 只要对象有 sound() 方法
print(animal_sound(Dog())) # Woof!
print(animal_sound(Cat())) # Meow!抽象类与接口
使用 abc 模块定义抽象基类——不能实例化,子类必须实现抽象方法:
from abc import ABC, abstractmethod
class AbstractAnimal(ABC):
@abstractmethod
def sound(self):
pass
class Dog(AbstractAnimal):
def sound(self): # 必须实现
return "Woof!"
# animal = AbstractAnimal() # TypeError对象生命周期
类定义 → 类对象创建 → 实例化 (__new__) → 初始化 (__init__)
→ 属性/方法调用 → 销毁 (__del__) → GC 回收
__new__:分配内存(极少需要重写)__init__:初始化实例__del__:实例销毁时调用(通常依赖 GC,不手动清理)
魔术方法一览
魔术方法(dunder methods)以双下划线包裹,为对象提供内置行为。
表示方法
| 方法 | 用途 | 触发 |
|---|---|---|
__str__ | 用户友好的字符串表示 | str()、print() |
__repr__ | 开发者用的”官方”表示 | repr()、交互环境 |
__format__ | 格式化字符串 | f"{obj:spec}" |
数学运算
| 运算符 | 魔术方法 |
|---|---|
+ | __add__ |
- | __sub__ |
* | __mul__ |
/ | __truediv__ |
// | __floordiv__ |
% | __mod__ |
** | __pow__ |
@ | __matmul__ |
class Vector:
def __init__(self, x, y):
self.x, self.y = x, y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
v = Vector(1, 2) + Vector(2, 3)
# v.x=3, v.y=5比较运算
| 运算符 | 魔术方法 |
|---|---|
== | __eq__ |
!= | __ne__ |
< | __lt__ |
<= | __le__ |
> | __gt__ |
>= | __ge__ |
容器方法
| 方法 | 用途 |
|---|---|
__len__ | len(obj) |
__getitem__ | obj[key] 读取 |
__setitem__ | obj[key] = val |
__delitem__ | del obj[key] |
__iter__ | 返回迭代器 |
__next__ | 迭代下一项 |
__contains__ | x in obj |
迭代器示例:
class Counter:
def __init__(self, start, end):
self.current, self.end = start, end
def __iter__(self):
return self
def __next__(self):
if self.current >= self.end:
raise StopIteration
value = self.current
self.current += 1
return value
for n in Counter(1, 4):
print(n) # 1, 2, 3属性访问
| 方法 | 触发时机 |
|---|---|
__getattr__ | 访问不存在的属性 |
__getattribute__ | 访问任何属性(优先于 __getattr__) |
__setattr__ | 设置任何属性 |
__delattr__ | 删除属性 |
class MyClass:
def __setattr__(self, name, value):
self.__dict__[name] = value # 防止递归
def __getattr__(self, name):
return f"{name} 不存在"上下文管理
class FileManager:
def __init__(self, filename):
self.filename = filename
def __enter__(self):
self.file = open(self.filename, 'r')
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
self.file.close()
# 返回 True 可抑制异常
with FileManager("data.txt") as f:
content = f.read()可调用对象 __call__
class Greeter:
def __init__(self, greeting="Hello"):
self.greeting = greeting
def __call__(self, name):
return f"{self.greeting}, {name}!"
hello = Greeter("Hello")
hello("John") # "Hello, John!"类型转换与判断
| 方法 | 触发 |
|---|---|
__int__ | int(obj) |
__float__ | float(obj) |
__bytes__ | bytes(obj) |
__bool__ | bool(obj)、if obj: |
__hash__ | hash(obj)(用于 dict key/set) |
定义了
__eq__但未定义__hash__的对象不可哈希。不可变对象才应实现__hash__。
描述符
实现了 __get__ / __set__ / __delete__ 的对象,用于控制属性访问:
class Descriptor:
def __get__(self, instance, owner):
return instance.__dict__.get(self.name)
def __set__(self, instance, value):
instance.__dict__[self.name] = valueproperty 就是 Python 内置的描述符实现(见下文)。
类方法与静态方法
class Example:
class_var = "Class Variable"
def instance_method(self): # 需要实例
return self
@classmethod
def class_method(cls): # 需要类
return cls.class_var
@staticmethod
def static_method(): # 不需要类或实例
return "utility"| 类型 | 第一个参数 | 可访问 | 适用场景 |
|---|---|---|---|
| 实例方法 | self | 实例 + 类属性 | 操作实例数据 |
| 类方法 | cls | 类属性 | 工厂方法、继承 |
| 静态方法 | 无 | 无 | 工具函数 |
property
@property 让方法像属性一样访问,同时保持控制逻辑:
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, value):
if value < -273.15:
raise ValueError("温度不能低于绝对零度")
self._celsius = value
@celsius.deleter
def celsius(self):
del self._celsius
t = Temperature(25)
print(t.celsius) # 25 — 像属性一样读取
t.celsius = 30 # 像属性一样赋值(触发 setter)属性保护约定
_name:单下划线 → 受保护(约定,仍可访问)__name:双下划线 → 名称修饰(_ClassName__name),更难外部访问
__slots__
限制实例可拥有的属性,节省内存(大量实例时有效):
class Point:
__slots__ = ['x', 'y']
def __init__(self, x, y):
self.x, self.y = x, y
p = Point(1, 2)
p.z = 3 # AttributeError代价:不能动态添加属性,不支持 __dict__,与某些 ORM/序列化库可能冲突。
关联
- 范式: 面向对象编程 — OOP 核心概念的跨语言视角
- TypeScript: 类型系统 — 结构化类型 vs 鸭子类型