Python3 【对象编程】避坑宝典:常见错误解析
以下是 15 个 Python 面向对象编程中的典型陷阱,包含错误代码、原因分析、修正方案及执行结果注释:
1. 方法忘记 self
参数
错误代码:
class MyClass:
def print_value(value): # 缺少 self
print(value)
obj = MyClass()
obj.print_value(10) # 报错: TypeError
原因:实例方法必须将 self
作为第一个参数。
修正:
class MyClass:
def print_value(self, value): # 添加 self
print(value)
obj = MyClass()
obj.print_value(10) # 输出: 10
2. 类变量与实例变量混淆
错误代码:
class Dog:
tricks = [] # 类变量(所有实例共享)
def add_trick(self, trick):
self.tricks.append(trick)
d1 = Dog()
d1.add_trick("打滚")
d2 = Dog()
print(d2.tricks) # 输出: ["打滚"](预期应为空)
原因:直接修改类变量,导致所有实例共享同一列表。
修正:
class Dog:
def __init__(self):
self.tricks = [] # 实例变量(每个实例独立)
def add_trick(self, trick):
self.tricks.append(trick)
d1 = Dog()
d1.add_trick("打滚")
d2 = Dog()
print(d2.tricks) # 输出: []
3. 忘记调用父类 __init__
错误代码:
class Animal:
def __init__(self, name):
self.name = name
class Cat(Animal):
def __init__(self, age):
self.age = age # 未调用父类 __init__
cat = Cat(2)
print(cat.name) # 报错: AttributeError
修正:
class Cat(Animal):
def __init__(self, name, age):
super().__init__(name) # 调用父类 __init__
self.age = age
cat = Cat("咪咪", 2)
print(cat.name) # 输出: 咪咪
4. 可变对象作为默认参数
错误代码:
class Student:
def __init__(self, name, grades=[]): # 默认空列表
self.grades = grades
self.name = name
s1 = Student("Alice")
s1.grades.append(90)
s2 = Student("Bob")
print(s2.grades) # 输出: [90](预期应为空)
修正:
class Student:
def __init__(self, name, grades=None):
self.grades = grades if grades else [] # 每次新建列表
self.name = name
s1 = Student("Alice")
s1.grades.append(90)
s2 = Student("Bob")
print(s2.grades) # 输出: []
5. 错误的多继承方法解析
错误代码:
class A:
def show(self):
print("A")
class B(A):
def show(self):
print("B")
class C(A):
def show(self):
print("C")
class D(B, C):
pass
d = D()
d.show() # 输出: B(可能预期为 C)
原因:继承顺序影响方法解析(MRO)。
修正:
class D(C, B): # 调整继承顺序
pass
d = D()
d.show() # 输出: C
6. 静态方法与实例方法混淆
错误代码:
class Calculator:
@staticmethod
def add(a, b):
return a + b
calc = Calculator()
print(calc.add(2, 3)) # 正确但不符合规范
print(Calculator.add(2,3)) # 更推荐的方式
说明:静态方法无需实例即可调用,但通过实例调用不会报错。
7. 动态添加未绑定的方法
错误代码:
class MyClass:
pass
def new_method():
print("Hello")
obj = MyClass()
obj.method = new_method
obj.method() # 报错: TypeError(缺少 self 参数)
修正:
import types
obj.method = types.MethodType(new_method, obj) # 绑定实例
obj.method() # 输出: Hello
8. 私有属性名称错误访问
错误代码:
class Secret:
def __init__(self):
self.__value = 42 # 名称被改写为 _Secret__value
s = Secret()
print(s.__value) # 报错: AttributeError
修正:
print(s._Secret__value) # 输出: 42(但不建议直接访问)
9. 未正确重写特殊方法
错误代码:
class MyList(list):
def __add__(self, other):
return self + other # 递归调用导致栈溢出
lst = MyList([1,2])
lst + [3] # 报错: RecursionError
修正:
class MyList(list):
def __add__(self, other):
return MyList(super().__add__(other))
lst = MyList([1,2]) + [3]
print(lst) # 输出: [1, 2, 3]
10. 装饰器未保留实例属性
错误代码:
def decorator(func):
def wrapper():
print("Decorated")
return func()
return wrapper
class MyClass:
@decorator
def method(self):
print("Hello")
obj = MyClass()
obj.method() # 报错: TypeError(缺少 self 参数)
修正:
from functools import wraps
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("Decorated")
return func(*args, **kwargs)
return wrapper
11. __del__
方法滥用
错误代码:
class File:
def __init__(self, name):
self.file = open(name, "w")
def __del__(self):
self.file.close() # 不可靠,可能未执行
f = File("test.txt")
f.file.write("Hello") # 正确关闭应显式调用 close()
建议:使用上下文管理器(with
语句)替代。
12. 运算符重载未返回新对象
错误代码:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __iadd__(self, other):
self.x += other.x
self.y += other.y
# 忘记返回 self
v1 = Vector(1, 2)
v2 = Vector(3, 4)
v1 += v2 # 报错: TypeError(返回 None)
修正:
def __iadd__(self, other):
self.x += other.x
self.y += other.y
return self # 返回修改后的对象
13. 误用生成器作为迭代器
错误代码:
class Counter:
def __init__(self, max):
self.max = max
def __iter__(self):
return (x for x in range(self.max)) # 生成器只能迭代一次
c = Counter(3)
print(list(c)) # 输出: [0,1,2]
print(list(c)) # 输出: [](预期重新迭代)
修正:
def __iter__(self):
for x in range(self.max): # 每次调用生成新迭代器
yield x
14. 动态属性未处理异常
错误代码:
class Flexible:
def __getattr__(self, name):
return self.__dict__[name] # 未处理不存在的属性
obj = Flexible()
print(obj.value) # 报错: KeyError
修正:
def __getattr__(self, name):
if name not in self.__dict__:
raise AttributeError(f"无属性 {name}")
return self.__dict__[name]
15. 类方法与实例方法混淆
错误代码:
class MyClass:
@classmethod
def class_method(cls):
print(f"类方法: {cls}")
def instance_method(self):
print("实例方法")
obj = MyClass()
obj.class_method() # 输出正常(但逻辑混淆)
MyClass.instance_method() # 报错: 缺少 self 参数
建议:明确区分类方法和实例方法的使用场景。
这些错误涵盖了 Python 面向对象编程中的常见陷阱,理解并避免它们能显著提升代码质量!