通过__call__魔法方法可以像使用函数一样使用对象。通过括号的方式调用,也可以像函数一样传入参数:
from icecream import ic
class Multiplier:
def __init__(self, mul):
self.mul = mul
def __call__(self, arg):
return self.mul * arg
o = Multiplier(3)
ic(o(4))
11:15:45|> o(4): 12
当我们对某个自定义对象使用len函数时,其实就是在调用这个魔术方法。
from icecream import ic
class MyList:
def __init__(self, data):
self._data = data
def __len__(self):
return len(self._data)
x = MyList([1, 2, 3])
ic(len(x))
if x:
ic('OK')
11:23:21|> len(x): 3
11:23:21|> ‘OK’
当我们用自定义的对象作为判断条件时,如果我们的自定义对象中没有定义__bool__魔术方法,那么会通过__len__魔术方法进行判断,不为空则返回True。
当我们尝试用[]
的形式调用或赋值对象中的元素时会用调用这两个魔术方法:
from icecream import ic
class MyList:
def __init__(self, data):
self._data = data
def __getitem__(self, key):
return self._data[key]
def __setitem__(self, key, value):
self._data[key] = value
x = MyList([1, 2, 3])
ic(x[2])
x[2] = 5
ic(x[2])
14:48:12|> x[2]: 3
14:48:13|> x[2]: 5
在del obj[n]时会调用这个魔术方法。
from icecream import ic
class MyList:
def __init__(self, data):
self._data = data
def __getitem__(self, key):
return self._data[key]
def __delitem__(self, key):
self._data = self._data[0:key] + self._data[key + 1:]
x = MyList([1, 2, 3])
ic(x[1])
del x[1]
ic(x[1])
14:55:20|> x[1]: 2
14:55:20|> x[1]: 3
reversed:reverse(obj)
当用Python内置的函数reverse对象时会调用对象内的该方法。
from icecream import ic
class MyList:
def __init__(self, data):
self._data = data
def __getitem__(self, key):
return self._data[key]
def __reversed__(self):
return MyList(self._data[::-1])
x = MyList([1, 2, 3])
ic(reversed(x)._data)
15:03:55|> reversed(x)._data: [3, 2, 1]
contains:item in obj
做in操作时会调用该方法。
from icecream import ic
class MyList:
def __init__(self, data):
self._data = data
def __contains__(self, item):
return item in self._data
x = MyList([1, 2, 3])
ic(1 in x)
ic(4 in x)
15:05:22|> 1 in x: True
15:05:22|> 4 in x: False
iter:iter(obj)
返回对象的迭代器(iter)时会调用该方法。
这个魔术方法必须是Python的字典类型数据的子类中才有作用。当在字典中找一个key而找不到时,会调用这个方法。
from icecream import ic
class MyDict(dict):
def __missing__(self, key):
return 1
d = MyDict()
ic(d[0])
15:10:06|> d[0]: 1
这两个魔术方法和上下文管理器有关,在之前的章节中已经详细介绍了。这里就不赘述了。