Python的魔法方法是特殊的方法,用于定义类的行为。它们以双下划线开头和结尾,例如__init__
、__str__
。魔法方法使对象行为变得更加直观和灵活。以下是一些常见的魔法方法:
1. __init__(self, ...)
初始化方法,在实例创建时自动调用,用于初始化对象的状态。
示例
class MyClass:
def __init__(self, value):
self.value = value
obj = MyClass(10)
print(obj.value) # 10
2. __new__(cls, ...)
构造方法,在创建实例之前调用,用于控制实例的创建过程。它负责返回一个新实例,是实例化对象的第一步。
__new__
与 __init__
的区别:
__new__
:
- 调用时机:__new__在创建对象之前被调用,是实例化对象的第一步。
- 作用:负责返回一个新的实例。它是一个静态方法,通常用于自定义对象的创建过程,特别是在继承不可变类型(如int、str、tuple)时。
- 返回值:必须返回一个类的实例(通常是通过调用super().new(cls)来实现)。
- 参数:接受类本身作为第一个参数(通常命名为cls),后续参数与__init__相同。
__init__
:
- 调用时机:__init__在对象创建之后被调用,是实例化对象的第二步。
- 作用:用于初始化对象的状态。它是一个实例方法,通常用于设置实例的属性或执行其他初始化操作。
- 返回值:不返回任何值(即返回None)。
- 参数:接受实例本身作为第一个参数(通常命名为self),后续参数用于初始化对象。
示例
class MyClass:
def __new__(cls, value):
print('创建MyClass实例')
return super().__new__(cls)
def __init__(self, value):
print('初始化MyClass')
self.value = value
obj = MyClass(10)
print(obj.value) # 创建MyClass实例 初始化MyClass 10
在这个示例中,__new__
方法首先调用了父类的__new__
方法来创建一个新实例,然后初始化了实例的value
属性。__init__
方法随后被调用来进一步初始化对象的状态。
3. __del__(self)
在对象被删除时调用,用于清理资源。
示例
class MyClass:
def __del__(self):
print("清除资源中...")
obj = MyClass()
del obj # 输出: 清除资源中...
4. __str__(self)
用于定义对象的字符串表示,print()
函数调用时使用。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __str__(self):
return f"传递的值为:{self.value}"
obj = MyClass(10)
print(obj) # 传递的值为:10
5. __repr__(self)
用于定义对象的官方字符串表示,这个方法的主要目的是为调试和开发提供清晰且准确的信息。当你在控制台中直接打印对象时,或者使用repr()函数时,__repr__方法会被调用。
repr 与 str 的区别:
- repr:提供对象的官方表示,目标是明确和准确,主要用于开发和调试。
- str:提供对象的非正式表示,目标是友好和可读,主要用于最终用户,也就是说str返回的结果可读性强,repr返回的结果更加准确。
如果只定义了__repr__而没有定义__str__,那么当调用print()或str()时,Python也会使用__repr__的返回值。
示例
class MyClass:
def __str__(self):
return '__str__'
def __repr__(self):
return '__repr__'
a
a = MyClass()
print(a) # __str__
print(repr(a)) # __repr__
# 交互模式下,直接输入对象a,调用的是__repr__方法
6. __len__(self)
定义对象的长度,len()
函数调用时使用。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __len__(self):
return len(self.value)
obj = MyClass([1, 2, 3, 4])
print(len(obj)) # 4
7. __getitem__(self, key)
定义对象的索引访问行为。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __getitem__(self, index):
return self.value[index]
obj = MyClass([1, 2, 3, 4])
print(obj[2]) # 3
8. __setitem__(self, key, value)
定义对象的索引赋值行为。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __setitem__(self, index, value):
self.value[index] = value
obj = MyClass([1, 2, 3, 4])
obj[2] = 10
print(obj.value) # [1, 2, 10, 4]
9. __delitem__(self, key)
定义对象的索引删除行为。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __delitem__(self, index):
del self.value[index]
obj = MyClass([1, 2, 3, 4])
del obj[2]
print(obj.value) # [1, 2, 4]
10. __iter__(self)
定义对象的迭代行为,for
循环调用时使用。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __iter__(self):
return iter(self.value)
obj = MyClass([1, 2, 3, 4])
for item in obj:
print(item) # 输出: 1 2 3 4
11. __contains__(self, item)
定义对象的成员检查行为,in
操作符调用时使用。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __contains__(self, item):
return item in self.value
obj = MyClass([1, 2, 3, 4])
print(3 in obj) # True
print(5 in obj) # False
12. __call__(self, ...)
使对象可以像函数一样被调用。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __call__(self, new_value):
self.value = new_value
obj = MyClass(10)
print(obj.value) # 10
obj(20)
print(obj.value) # 20
13. __add__(self, other)
定义对象的加法行为,+
操作符调用时使用。类似的魔法方法还有__sub__
(减法)、__mul__
(乘法)、__truediv__
(除法)等。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __add__(self, other):
return MyClass(self.value + other.value)
obj1 = MyClass(10)
obj2 = MyClass(20)
obj3 = obj1 + obj2
print(obj3.value) # 30
14. __eq__(self, other)
定义对象的相等比较行为,==
操作符调用时使用。类似的魔法方法还有__ne__
(不等)、__lt__
(小于)、__le__
(小于等于)、__gt__
(大于)、__ge__
(大于等于)等。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __eq__(self, other):
return self.value == other.value
obj1 = MyClass(10)
obj2 = MyClass(10)
obj3 = MyClass(20)
print(obj1 == obj2) # True
print(obj1 == obj3) # False
15. __enter__
和 __exit__
定义对象的上下文管理行为,支持with
语句。
示例
class MyContext:
def __enter__(self):
print("进入上下文")
return self
def __exit__(self, exc_type, exc_value, traceback):
print("退出上下文")
with MyContext():
print("上下文操作中")
'''
输出:
进入上下文
上下文操作中
退出上下文
'''
16. __getattr__(self, name)
和 __setattr__(self, name, value)
定义对象的属性访问和赋值行为。需要注意的是,为了避免无限递归,需要直接操作实例的__dict__属性。
示例
class MyClass:
def __getattr__(self, name):
return f"你所访问的属性{name}不存在"
def __setattr__(self, name, value):
print(f"设置属性{name}为{value}")
self.__dict__[name] = value
a = MyClass()
print(a.name) # 你所访问的属性name不存在
a.name = "lee" # 设置属性name为lee
print(a.name) # lee
17. __delattr__(self, name)
定义对象的属性删除行为。
示例
class MyClass:
def __delattr__(self, name):
print(f"删除属性 {name}")
super().__delattr__(name)
obj = MyClass()
obj.age = 18
del obj.age # 删除属性 age
18. __dir__(self)
自定义对象的属性列表,dir()
函数调用时使用。
示例
class MyClass:
def __dir__(self):
return ['a', 'b']
obj = MyClass()
print(dir(obj)) # ['a', 'b']
19. __format__(self, format_spec)
定义对象的格式化行为,format()
函数和f-strings调用时使用。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __format__(self, __format_spec):
if __format_spec == 'a':
return f"*** {self.value} ***"
return str(self.value)
obj = MyClass(18)
print(format(obj, 'a')) # *** 18 ***
print(f"{obj:a}") # *** 18 ***
print(f'{obj:b}') # 18
20. __hash__(self)
定义对象的哈希值,使对象可用作字典键或存储在集合中。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __hash__(self):
return hash(self.value)
obj = MyClass('a')
print(hash(obj)) # 输出对象的哈希值 7582294177259239944
21. __bool__(self)
定义对象的布尔值转换行为,bool()
函数和条件语句调用时使用。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __bool__(self):
return bool(self.value)
obj1 = MyClass(0)
obj2 = MyClass(10)
print(bool(obj1)) # False
print(bool(obj2)) # True
22. __getattribute__(self, name)
自定义属性访问行为。这个方法在访问任何属性时都会被调用,甚至包括魔法方法和内置方法调用,因此需要小心避免无限递归。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __getattribute__(self, name):
print(f"访问属性 {name}")
return super().__getattribute__(name)
obj = MyClass(10)
print(obj.value) # 访问属性 value 10
23. __missing__(self, key)
定义字典类的缺失键行为,适用于子类化的字典类型。
示例
class MyDict(dict):
def __missing__(self, key):
return f"{key} not found"
my_dict = MyDict(a=1, b=2)
print(my_dict['a']) # 1
print(my_dict['c']) # c not found
24. __index__(self)
定义对象在使用索引操作时的行为,例如在切片操作中使用对象。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __index__(self):
return self.value
obj = MyClass(3)
my_list = [1,2,3,4,5]
print(my_list[obj]) # 4
print(my_list[1:obj]) # [2,3]
25. __round__(self, n)
定义对象的舍入行为,round()
函数调用时使用。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __round__(self, n=None):
return round(self.value, n)
obj = MyClass(5.678)
print(round(obj, 2)) # 5.68
26. __reversed__(self)
定义对象的反向迭代行为,reversed()
函数调用时使用。
示例
class MyClass:
def __init__(self, value):
self.value = value
def __reversed__(self):
return reversed(self.value)
obj = MyClass([1, 2, 3, 4])
print(list(reversed(obj))) # [4, 3, 2, 1]
27. __matmul__(self, other)
定义矩阵乘法行为,@
操作符调用时使用。类似的魔法方法还有__imatmul__
。
示例
import numpy as np
class Matrix:
def __init__(self, matrix):
self.matrix = matrix
def __matmul__(self, other):
return Matrix(np.matmul(self.matrix, other.matrix))
def __repr__(self):
return str(self.matrix)
m1 = Matrix([[1, 2], [3, 4]])
m2 = Matrix([[5, 6], [7, 8]])
print(m1 @ m2) # [[19 22] [43 50]]