zoukankan      html  css  js  c++  java
  • 魔法方法之自定义序列

    自定义序列

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

  • 相关阅读:
    PCL配置即常见问题
    opencv2.4.9配置+VS2013
    我的项目配置问题及解决
    Java 8 函数式编程
    leecode刷题(17)-- 实现StrStr
    leecode刷题(16)-- 字符串转换整数
    leecode刷题(15)-- 验证回文字符串
    博客迁移通知
    leecode刷题(14)-- 有效的字母异位词
    leecode刷题(13) -- 字符串中的第一个唯一字符
  • 原文地址:https://www.cnblogs.com/freely/p/6756416.html
Copyright © 2011-2022 走看看