python魔术方法详解

python魔术方法详解
最新回答
你是我所有的梦

2023-04-11 08:17:18

Python魔术方法(Magic Methods)是类中以双下划线__开头和结尾的特殊方法,用于定义类的特定行为。以下是关键魔术方法的详细说明及示例:

1. 构造方法 __init__
  • 作用:对象创建时自动调用,用于初始化实例属性。
  • 示例:class FooBar: def __init__(self): self.somevar = 42f = FooBar()print(f.somevar) # 输出: 42
2. 继承与构造方法重写
  • 问题:子类重写__init__时,需调用父类构造方法以确保属性正确初始化。
  • 方法1:未绑定方法调用class Bird: def __init__(self): self.hungry = Trueclass SongBird(Bird): def __init__(self): Bird.__init__(self) # 显式调用父类构造方法 self.sound = 'Squawk!'
  • 方法2:使用super()(推荐,需新式类)class Bird: def __init__(self): self.hungry = Trueclass SongBird(Bird): def __init__(self): super().__init__() # Python 3简化写法 self.sound = 'Squawk!'
3. 属性访问控制(1) 传统方法:getter/setter
  • 通过方法封装属性访问:class Rectangle: def __init__(self): self.width = 0 self.height = 0 def setSize(self, size): self.width, self.height = size def getSize(self): return self.width, self.heightr = Rectangle()r.setSize((10, 5))print(r.getSize()) # 输出: (10, 5)
(2) @property装饰器(推荐)
  • 将方法伪装为属性,实现更优雅的访问:class Rectangle: def __init__(self): self._width = 0 # 内部变量建议用下划线前缀 self._height = 0 @property def width(self): return self._width @width.setter def width(self, value): if value > 0: self._width = value else: raise ValueError("Width must be positive")r = Rectangle()r.width = 10 # 调用setterprint(r.width) # 调用getter,输出: 10
(3) property()函数
  • 旧式写法,功能与@property相同:class Rectangle: def __init__(self): self._width = 0 self._height = 0 def get_width(self): return self._width def set_width(self, value): if value > 0: self._width = value width = property(get_width, set_width)
4. 其他常用魔术方法(1) 字符串表示 __str__ 和 __repr__
  • __str__:用户友好字符串,str(obj)或print(obj)时调用。
  • __repr__:开发者友好字符串,repr(obj)或交互式环境直接显示时调用。class Point: def __init__(self, x, y): self.x = x self.y = y def __str__(self): return f"Point({self.x}, {self.y})" def __repr__(self): return f"Point(x={self.x}, y={self.y})"p = Point(1, 2)print(p) # 输出: Point(1, 2)(调用__str__)print(repr(p)) # 输出: Point(x=1, y=2)(调用__repr__)
(2) 运算符重载 __add__, __eq__ 等
  • 自定义运算符行为:class Vector: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): return Vector(self.x + other.x, self.y + other.y) def __eq__(self, other): return self.x == other.x and self.y == other.yv1 = Vector(1, 2)v2 = Vector(3, 4)v3 = v1 + v2 # 调用__add__print(v3.x, v3.y) # 输出: 4 6print(v1 == v2) # 输出: False(调用__eq__)
(3) 容器行为 __len__, __getitem__
  • 使类支持类似列表的操作:class MyList: def __init__(self, items): self.items = list(items) def __len__(self): return len(self.items) def __getitem__(self, index): return self.items[index]ml = MyList([1, 2, 3])print(len(ml)) # 输出: 3(调用__len__)print(ml[1]) # 输出: 2(调用__getitem__)
5. 新式类与旧式类
  • 新式类:继承自object或使用_metaclass_ = type,支持super()和描述符协议。
  • 旧式类:不继承object,功能受限(Python 3中已无此区分)。# 确保新式类_metaclass_ = type # Python 2中显式声明class NewType(object): # Python 3中默认继承object pass
总结
  • 构造方法:__init__初始化对象,子类需正确调用父类构造方法。
  • 属性控制:优先使用@property实现安全、灵活的属性访问。
  • 运算符与容器:通过魔术方法自定义类在运算符、迭代等场景的行为。
  • 新式类:始终使用新式类以获得完整功能(Python 3无需额外操作)。

通过合理使用魔术方法,可以显著提升Python类的功能性和代码优雅度。