zoukankan      html  css  js  c++  java
  • Invoking Descriptors

    描述符用法建议,
    内置的 property 类创建的是
    '覆盖型'(date descriptor), 实现了 __set____get__. 特性 property 的 __set__ 方法 默认会抛出 'AttributeError: can not set attribute', 也就是说使用 property 是创建'只读'属性的一个简单的方式。 然而, 如果通过 descriptor 来实现'只读' 属性, 一定要 同时实现 __set____get__ 方法, 否则, 实例的同名属性会遮盖 descriptor. 用于验证数据的 descriptor 可以只有 __set__ 方法 来 验证数据的有效性. 如果有效, 使用 'descriptor 实例' 的名称为 '', 在'实例'__dict__ 属性中设置。 从'实例'中读取同名属性的速度更快, 因为不需要经过 __get__ 方法处理. 如果只实现了 __get__ 方法, 是'非覆盖型'(non-data) descriptor. 这类描述符适用于执行一些耗费资源的计算, 然后向'实例'设置同名属性, 以缓存结果. 同名的'实例属性'会遮盖 descriptor, 因此, 后面再访问会直接从实例的 __dict__ 属性中的到值, 不会触发描述符的 __get__ 方法.
    Invoking descriptors, In general, a descriptor
    is an object attribute with “binding behavior”, one whose attribute access has been overridden by methods in the descriptor protocol: __get__(), __set__(), and __delete__(). If any of those methods are defined for an object, it is said to be a descriptor. The default behavior for attribute access is to get, set, or delete the attribute from an object’s dictionary. For instance, a.x has a lookup chain starting with a.__dict__['x'], then type(a).__dict__['x'], and continuing through the base classes of type(a) excluding metaclasses. However, if the looked-up value is an object defining one of the descriptor methods, then Python may override the default behavior and invoke the descriptor method instead. Where this occurs in the precedence chain depends on which descriptor methods were defined and how they were called. The starting point for descriptor invocation is a binding, a.x. How the arguments are assembled depends on a: Direct Call The simplest and least common call is when user code directly invokes a descriptor method: x.__get__(a). Instance Binding If binding to an object instance, a.x is transformed into the call: type(a).__dict__['x'].__get__(a, type(a)). Class Binding If binding to a class, A.x is transformed into the call: A.__dict__['x'].__get__(None, A). Super Binding If a is an instance of super, then the binding super(B, obj).m() searches obj.__class__.__mro__ for the base class A immediately preceding B and then invokes the descriptor with the call: A.__dict__['m'].__get__(obj, obj.__class__). For instance bindings, the precedence of descriptor invocation depends on the which descriptor methods are defined. A descriptor can define any combination of __get__(), __set__() and __delete__(). If it does not define __get__(), then accessing the attribute will return the descriptor object itself unless there is a value in the object’s instance dictionary. If the descriptor defines __set__() and/or __delete__(), it is a data descriptor; if it defines neither, it is a non-data descriptor. Normally, data descriptors define both __get__() and __set__(), while non-data descriptors have just the __get__() method. Data descriptors with __set__() and __get__() defined always override a redefinition in an instance dictionary. In contrast, non-data descriptors can be overridden by instances. Python methods (including staticmethod() and classmethod()) are implemented as non-data descriptors. Accordingly, instances can redefine and override methods. This allows individual instances to acquire behaviors that differ from other instances of the same class. The property() function is implemented as a data descriptor. Accordingly, instances cannot override the behavior of a property.
  • 相关阅读:
    Linux系统中DHCP的配置
    Linux系统下第三方软件安装实例
    Linux系统在启动过程中mbr主引导程序被破坏的解决方案
    Linux系统在启动过程中启动级别发生错误的解决办法
    Linux系统下超级用户密码的修改
    Linux系统在启动过程中内核文件丢失的解决方法
    Linux系统在启动过程中grub引导文件丢失的解决方法
    Linux之FTP服务
    Linux之LVM设备的管理
    Linux下设备的基本管理
  • 原文地址:https://www.cnblogs.com/zzyzz/p/7575743.html
Copyright © 2011-2022 走看看