魔法方法之自定义序列

自定义序列

  自定义序列的相关魔法方法允许我们自己创建的类拥有序列的特性,让其使用起来就像 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

posted @ 2017-04-24 13:19  似是故人来~  阅读(303)  评论(0编辑  收藏  举报