魔法方法之自定义序列
自定义序列
自定义序列的相关魔法方法允许我们自己创建的类拥有序列的特性,让其使用起来就像 python 的内置序列(dict,tuple,list,string等)。
因为如果要定制容器类型的话需要用到这些协议。首先,实现不变容器的话有一个协议:实现不可变容器,你只能定义__len__
和 __getitem__
(一会会讲更多)。可变容器协议则需要所有不可变容器的所有另外还需要 增加定义__setitem__
和 __delitem__
。 。最终,如果你希望你的对象是可迭代的话,你需要定义 __iter__
会返回一个迭代器。迭代器必须遵循迭代器协议,需要有 __iter__
(返回它本身) 和 next
。
容器背后的魔法方法
-
__len__(self)
需要返回数值类型,以表示容器的长度。该方法在可变容器和不可变容器中必须实现。
__getitem__(self, key)
当你执行
self[key]
的时候,调用的就是该方法。该方法在可变容器和不可变容器中也都必须实现。
调用的时候,如果key的类型错误,该方法应该抛出TypeError;
如果没法返回key对应的数值时,该方法应该抛出ValueError。__setitem__(self, key, value)
当你执行
self[key] = value
时,调用的是该方法。__delitem__(self, key)
当你执行
del self[key]
的时候,调用的是该方法。 -
如:
class Foo(object): def __getitem__(self, key): print('__getitem__', key) def __setitem__(self, key, value): print('__setitem__', key, value) def __delitem__(self, key): print('__delitem__', key) obj = Foo() result = obj['k1'] # 自动触发执行 __getitem__ obj['k2'] = 'Mike' # 自动触发执行 __setitem__ del obj['k1'] #执行结果 __getitem__ k1 __setitem__ k2 Mike __delitem__ k1
__iter__(self)
该方法需要返回一个迭代器(iterator)。当你执行
for x in container:
或者使用iter(container)
时,该方法被调用。__reversed__(self)
如果想要该数据结构被內建函数
reversed()
支持,就还需要实现该方法。__contains__(self, item)
如果定义了该方法,那么在执行
item in container
或者item not in container
时该方法就会被调用。
如果没有定义,那么Python会迭代容器中的元素来一个一个比较,从而决定返回True或者False。__missing__(self, key)
dict
字典类型会有该方法,它定义了key如果在容器中找不到时触发的行为。
比如d = {'a': 1}
, 当你执行d[notexist]
时,d.__missing__['notexist']
就会被调用。
example:
class FunctionalList: '''一个列表的封装类,实现了一些额外的函数式 方法,例如head, tail, init, last, drop和take。''' def __init__(self, values=None): if values is None: self.values = [] else: self.values = values def __len__(self): return len(self.values) def __getitem__(self, key): # 如果键的类型或值不合法,列表会返回异常 return self.values[key] def __setitem__(self, key, value): self.values[key] = value def __delitem__(self, key): del self.values[key] def __iter__(self): return iter(self.values) def __reversed__(self): return reversed(self.values) def append(self, value): self.values.append(value) def head(self): # 取得第一个元素 return self.values[0] def tail(self): # 取得除第一个元素外的所有元素 return self.valuse[1:] def init(self): # 取得除最后一个元素外的所有元素 return self.values[:-1] def last(self): # 取得最后一个元素 return self.values[-1] def drop(self, n): # 取得除前n个元素外的所有元素 return self.values[n:] def take(self, n): # 取得前n个元素 return self.values[:n]
参考:http://pycoders-weekly-chinese.readthedocs.io/en/latest/issue6/a-guide-to-pythons-magic-methods.html#id14