Python 魔术方法基础
魔术方法(Magic Methods)以双下划线开头和结尾,用于定制类的内置行为。
init:初始化
Python
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 25)
print(p.name) # Alice
print(p.age) # 25
__init__在实例创建后自动调用,用于初始化实例属性。
str 与 repr
Python
class Product:
def __init__(self, name, price):
self.name = name
self.price = price
def __str__(self):
"用户友好的字符串表示"
return f"{self.name}: ¥{self.price}"
def __repr__(self):
"开发者友好的表示,应能重建对象"
return f"Product('{self.name}', {self.price})"
p = Product("苹果", 5.5)
# __str__ 用于 print 和 str()
print(p) # 苹果: ¥5.5
print(str(p)) # 苹果: ¥5.5
# __repr__ 用于 repr() 和调试
print(repr(p)) # Product('苹果', 5.5)
# 在交互式环境中显示 __repr__
p # Product('苹果', 5.5)
# 可重建对象
p2 = eval(repr(p))
print(p2.name) # 苹果
| 方法 | 用途 | 触发时机 |
|---|---|---|
__str__ | 用户友好显示 | print(obj)、str(obj) |
__repr__ | 开发者友好显示 | repr(obj)、交互式显示 |
len
Python
class Bookshelf:
def __init__(self, books):
self.books = books
def __len__(self):
return len(self.books)
shelf = Bookshelf(["Python", "Go", "Java"])
print(len(shelf)) # 3
bool
Python
class Stack:
def __init__(self):
self.items = []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop() if self.items else None
def __len__(self):
return len(self.items)
def __bool__(self):
return len(self.items) > 0
stack = Stack()
print(bool(stack)) # False
stack.push(1)
print(bool(stack)) # True
if stack: # 使用 __bool__
print("栈非空")
getitem、setitem、delitem
Python
class DictLike:
def __init__(self):
self.data = {}
def __getitem__(self, key):
return self.data[key]
def __setitem__(self, key, value):
self.data[key] = value
def __delitem__(self, key):
del self.data[key]
def __contains__(self, key):
return key in self.data
d = DictLike()
d['a'] = 1 # __setitem__
d['b'] = 2
print(d['a']) # 1 (__getitem__)
del d['b'] # __delitem__
print('a' in d) # True (__contains__)
print('b' in d) # False
iter 与 next
Python
class Counter:
def __init__(self, start, end):
self.current = start
self.end = 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 num in Counter(0, 5):
print(num) # 0, 1, 2, 3, 4
eq 与其他比较方法
Python
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
return self.x == other.x and self.y == other.y
def __lt__(self, other):
return (self.x, self.y) < (other.x, other.y)
def __le__(self, other):
return self == other or self < other
p1 = Point(1, 2)
p2 = Point(1, 2)
p3 = Point(2, 1)
print(p1 == p2) # True (__eq__)
print(p1 < p3) # True (__lt__)
print(p1 <= p2) # True (__le__)
| 方法 | 操作符 | 说明 |
|---|---|---|
__eq__ | == | 相等比较 |
__ne__ | != | 不相等(默认使用 __eq__ 结果取反) |
__lt__ | < | 小于 |
__le__ | <= | 小于等于 |
__gt__ | > | 大于 |
__ge__ | >= | 大于等于 |
hash
Python
class Card:
def __init__(self, suit, rank):
self.suit = suit
self.rank = rank
def __eq__(self, other):
return (self.suit, self.rank) == (other.suit, other.rank)
def __hash__(self):
return hash((self.suit, self.rank))
c1 = Card("红桃", "A")
c2 = Card("红桃", "A")
# 可用作字典键和集合元素
cards = {c1: "王牌"}
cards[c2] = "也是王牌"
print(len(cards)) # 1(因为 c1 == c2)
s = {c1, c2}
print(len(s)) # 1
实现
__hash__的对象必须同时实现__eq__,且相等对象的哈希值必须相同。
call
Python
class Multiplier:
def __init__(self, factor):
self.factor = factor
def __call__(self, value):
return value * self.factor
double = Multiplier(2)
print(double(10)) # 20(像函数一样调用)
print(type(double)) # Multiplier(仍是类实例)
new:创建实例
Python
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, name):
self.name = name
s1 = Singleton("first")
s2 = Singleton("second")
print(s1 is s2) # True
print(s1.name) # second(__init__ 再次调用)
__new__在__init__之前调用,负责创建实例对象。
del:析构
Python
class Resource:
def __init__(self, name):
self.name = name
print(f"{self.name} 创建")
def __del__(self):
print(f"{self.name} 销毁")
r = Resource("资源A")
# 程序结束或 del r 时调用 __del__
del r # 资源A 销毁
__del__不保证一定调用,建议使用上下文管理器管理资源。
enter 与 exit
Python
class FileHandler:
def __init__(self, filename):
self.filename = filename
def __enter__(self):
self.file = open(self.filename, 'w')
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
self.file.close()
return False # 不抑制异常
with FileHandler('test.txt') as f:
f.write("Hello")
# 自动关闭文件
常用魔术方法分类
| 类别 | 方法 |
|---|---|
| 初始化 | __init__、__new__ |
| 字符表示 | __str__、__repr__ |
| 容器模拟 | __len__、__getitem__、__setitem__、__delitem__ |
| 迭代 | __iter__、__next__ |
| 比较 | __eq__、__lt__、__le__、__gt__、__ge__ |
| 哈希 | __hash__ |
| 可调用 | __call__ |
| 上下文 | __enter__、__exit__ |
要点总结
| 方法 | 用途 |
|---|---|
__init__ | 初始化实例 |
__str__ | 用户显示 |
__repr__ | 开发者显示 |
__len__ | len() 支持 |
__getitem__ | 索引访问 |
__eq__ | == 比较 |
__call__ | 函数式调用 |
魔术方法是 Python 的内置行为钩子,定制这些方法可改变类的默认行为。
D:\git2\jwdev\articles\PYTHON\进阶\面向对象编程\魔术方法基础.md
📝 发现内容有误?点击此处直接编辑