从实例

时间:2017-07-04 20:16:05

标签: python python-3.x

从坚果壳中的Python

  

从实例获取属性

     

当您使用语法x.name来引用属性时   类x的实例C,查找分三步进行:

     
      
  1. name(或其中一个C的祖先类)中找到C作为覆盖描述符的名称v (即   type(v)提供方法__get____set__

         

    x.name的值是type(v).__get__(v, x, C) 的结果

  2.   
  3. 否则,namex.__dict__

    中的关键字      

    x.name获取并返回x.__dict__['name']

  4. 处的值   
  5. 否则,x.name会将查询委托给x的类(根据C.name使用的相同的两步查找,就像   详细)

         

    找到描述符v时,整体结果如下   属性查找再次是type(v).__get__(v, x, C)

         

    •找到非描述性值v时,总体而言   属性查找的结果只是v

  6.         

    当这些查找步骤找不到属性时,Python会引发AttributeError异常。但是,对于x.name的查找,C定义或继承特殊内容时   方法__getattr__,Python调用C.__getattr__(x,'name')而不是提升   例外。然后,最多__getattr__返回合适的值或加注   适当的例外,通常是AttributeError

  1. 步骤1和步骤3的第一部分是否相同?如果是,为什么同一步骤出现两次?

  2. name(或其中一个C的祖先类)中找到C作为覆盖描述符的名称时,它们是否都发生 v

  3. __getattribute__(self, name) 
    
         

    每次访问属性x.y的请求都会调用Python   x.__getattribute__('y'),必须获取并返回属性   价值或者提高AttributeError。正常的语义   属性访问(使用x.__dict__C.__slots__C的类   属性x.__getattr__)全部归于object.__getattribute__。   当类C覆盖__getattribute__时,它必须实现所有   它想要提供的属性访问语义。最常见的是,最多   实现属性访问语义的便捷方法是   委派(例如,将object.__getattribute__(self, ...)称为部分   覆盖__getattribute__)的操作。

1 个答案:

答案 0 :(得分:2)

  

步骤1和步骤3的第一部分是否相同?如果是,为什么同一步骤出现两次?

第1步需要__get____set__(实际上,__set____delete__以及__get__都会触发它。如果通过步骤1或2找不到属性,则无条件地执行步骤3.

  

当它们在C(或C的祖先类之一)中找到名称作为覆盖描述符v的名称时,它们是否都会发生?

没有。 “覆盖描述符”触发第1步;另一种描述符或非描述符将仅在步骤3中考虑。(官方Python文档不使用术语“覆盖描述符”;它们引用具有__set____delete__的描述符作为“数据描述符”,如果数据描述符具有__get__,则__get__将优先于实例dict中找到的对象。)