这期我们接着聊聊拥有模拟
功能的魔术方法。
__call__魔术方法
在 Python 中,每个类都是可调用的对象(callable),这意味着你可以像调用函数一样调用一个类来创建新的实例。__call__
是一个特殊的方法,用于使 Python 类的实例能够像函数一样被调用。
当你调用一个实例时,Python 会查找该实例所属类的 __call__
方法。如果该方法存在,则 Python 会调用该方法,将实例和任何参数传递给该方法,然后返回方法的结果。
下面是一个示例,演示了如何使用 __call__
方法:
class Adder:
def __init__(self, x):
self.x = x
def __call__(self, y):
return self.x + y
add = Adder(10)
print(add(5)) # Output: 15
在这个示例中,我们定义了一个 Adder
类,它有一个构造函数和一个 __call__
方法。__call__
方法接受一个参数 y
,并返回 self.x + y
的结果。我们实例化一个 Adder
对象,将 x
设置为 10,然后使用括号运算符调用该实例,并将参数 5
传递给它。该调用返回 15
,这是 10 + 5
的结果。
注意,当你调用一个实例时,Python 实际上是在查找类的 __call__
方法,而不是实例的 __call__
方法。如果类没有定义 __call__
方法,Python 会抛出 TypeError
异常。
__len__魔术方法
__len__
是Python中的一个魔术方法,用于定义类的实例对象的长度。该方法用于返回一个对象的长度,通常是容器类型的对象,如字符串、列表、元组和字典等。
以下是一个使用__len__
魔术方法的例子:
class MyList:
def __init__(self, lst):
self.lst = lst
def __len__(self):
return len(self.lst)
lst = MyList([1, 2, 3, 4, 5])
print(len(lst)) # 输出: 5
在上面的例子中,MyList
类中定义了__len__
方法,该方法返回了MyList
实例对象的长度。当我们调用len()
函数时,它将会自动调用该对象的__len__
方法来获取其长度。
注意,只有实现了__len__
方法的对象才能够使用len()
函数获取其长度。如果对象没有实现该方法,则会引发TypeError
异常。
__length_hint__魔术方法
__length_hint__
是 Python 3.4 新增的一个魔术方法,用于返回一个对象的估计长度。该方法通常被迭代器实现,可以让一些 Python 函数(如 len()
)更加高效地工作。
当我们对一个对象调用 len()
函数时,如果该对象没有实现 __len__
方法,那么 Python 解释器就会尝试使用迭代器来估计对象的长度。而在这个过程中,就会调用对象的 __length_hint__
方法来获取对象的估计长度。
需要注意的是,__length_hint__
方法并不要求返回准确的对象长度,只需要返回一个大致的估计即可。如果对象的长度无法估计,也可以返回 NotImplemented
表示无法处理。
以下是一个简单的示例,演示了如何使用 __length_hint__
方法实现自定义迭代器对象:
import operator
class MyIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index >= len(self.data):
raise StopIteration
value = self.data[self.index]
self.index += 1
return value
def __length_hint__(self