前言 本文着重介绍
基本序列协议: __len__和__getitem__ 
带有多个条目对象的安全展示 
合理的切片支持 
哈希处理 
自定义格式化语言拓展 
 
Vector: 自定义序列类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class  Vector :    typecode = 'd'      def  __init__ (self, components ):         self._components = array(self.typecode, components)     def  __iter__ (self ):         return  iter (self._components)     def  __repr__ (self ):         components = reprlib.repr (self._components)         components = components[components.find('[' ):-1 ]         return  'Vector({})' .format (components)     def  __str__ (self ):         return  str (tuple (self))     def  __bytes__ (self ):         return  bytes ([ord (self.typecode)]) + bytes (self._components)     def  __eq__ (self, other ):         return  tuple (self) == tuple (other)     def  __abs__ (self ):         return  math.sqrt(sum (x * x for  x in  self))     def  __bool__ (self ):         return  bool (abs (self))     @classmethod     def  frombytes (cls, octets ):         typecode = chr (octets[0 ])         memv = memoryview (octets[1 :]).cast(typecode)         return  cls(memv) 
 
协议和鸭子类型 为Vector实现__len__和__getitem__协议
1 2 3 4 5 6 def  __len__ (self ):    return  len (self._components) def  __getitem__ (self, item ):    return  self._components[item] 
 
增强切片功能 1 2 3 4 5 6 7 8 9 10 def  __getitem__ (self, item ):    cls = type (self)     if  isinstance (item, slice ):         return  cls(self._components[item])     elif  isinstance (item, numbers.Integral):         return  self._components[item]     else :         msg = '{cls.__name__} indices must be integers'          raise  TypeError(msg.format (cls=cls)) 
 
动态属性访问 __getattr__当属性查找失败被调用。简单来说就是,给定表达式my_obj.x, Python检查对象是否含有x属性。如果没有,继续寻找类(my_obj.__class__),然后继承链向上查找。如果依然没有找到x,那么__getattr__就会被调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 def  __getattr__ (self, name ):    cls = type (self)     if  len (name) == 1 :         pos = cls.shortcut_names.find(name)         if  0  <= pos < len (self._components):             return  self._components[pos]     msg = '{.__name__!r} object has no attribute {!r}'      raise  AttributeError(msg.format (cls, name)) def  __setattr__ (self, name, value ):    cls = type (self)     if  len (name) == 1 :         if  name in  cls.shortcut_names:             error = 'readonly attribute {attr_name!r}'          elif  name.islower():             error = "can't set attributes 'a' to 'z' in {cls_name!r}"          else :             error = ''          if  error:             msg = error.format (cls_name=cls.__name__, attr_name=name)             raise  AttributeError(msg)     super ().__setattr__(name, value) 
 
哈希和更快的== 1 2 3 4 5 6 7 def  __hash__ (self ):    hashes = map (hash , self._components)     return  functools.reduce(operator.xor, hashes, 0 ) def  __eq__ (self, other ):    return  len (self) == len (other) and  all (a == b for  a, b in  zip (self, other)) 
 
格式化 1 2 3 4 5 6 7 8 9 10 11 12 13 def  __format__ (self, fmt_spec ):    if  fmt_spec.endswith('h' ):         fmt_spec = fmt_spec[:-1 ]         coords = itertools.chain([abs (self), self.angles()])         outer_fmt = '<{}>'      else :         coords = self         outer_fmt = '({})'      components = (format (c, fmt_spec) for  c in  coords)     return  outer_fmt.format (', ' .join(components))