• 对特殊方法的访问


     1 对特殊方法的访问 - Special method lookup
     2 
     3     对于用户自定义的 class 来说, 特殊方法只有通过定义对象的类型object’s type (而非通过 instance
     4__dict__属性)被定义, 才能保证特殊方法的隐式调用.
     5     也就是说给自定义的 class 打 特殊方法的 monkey patching 后,再通过 conventional'传统方式' 调用是行不通的.
     6         注, conventional'传统方式' 调用 指的是如下面例子中 len() 跟 __len__() 的对应关系.
     7     见下例的 exception,
     8         例,
     9             >>> class C:
    10             ...     pass
    11             ...
    12             >>> c = C()
    13             >>> c.__len__ = lambda: 5
    14             >>> c.__len__()
    15             5
    16             >>> len(c)
    17             Traceback (most recent call last):
    18               File "<stdin>", line 1, in <module>
    19             TypeError: object of type 'C' has no len()
    20 
    21         报错的原因在于, 所有对象(包括类型对象) 都有实现特殊方法, 如果通过'传统方式'隐式调用
    22         这些特殊方法(len(c)), 当在类型对象本身上调用对应的特殊方法的时候便会失败.
    23         详见 python doc 中的描述,
    24             The rationale behind this behaviour lies with a number of special methods such as __hash__() and __repr__()
    25             that are implemented by all objects, including type objects.
    26             If the implicit lookup of these methods used the conventional lookup process,
    27             they would fail when invoked on the type object itself:
    28 
    29         例如,
    30             >>> 1 .__hash__() == hash(1)
    31             True
    32             >>> int.__hash__() == hash(int)
    33             Traceback (most recent call last):
    34               File "<stdin>", line 1, in <module>
    35             TypeError: descriptor '__hash__' of 'int' object needs an argument
    36 
    37             错误在于, 试图去调用一个类(int) 的 unbound method(__hash__), 有时这样的错误调用行为
    38             被称作‘metaclass confusion’. 可以采取通过 instance 访问 special methods
    39             的方式绕过 ‘metaclass confusion’.
    40             >>> type(1).__hash__(1) == hash(1)
    41             True
    42             >>> type(int).__hash__(int) == hash(int)
    43             True
    44 
    45             这样做的另外的一个好处是, 对特殊方法的隐式调用同时也绕过 __getattribute__ 方法,
    46             对该对象的的 metaclass 来说也是这样.
    47             >>> class Meta(type):
    48             ...     def __getattribute__(*args):
    49             ...         print("Metaclass getattribute invoked")
    50             ...         return type.__getattribute__(*args)
    51             ...
    52             >>> class C(object, metaclass=Meta):
    53             ...     def __len__(self):
    54             ...         return 10
    55             ...     def __getattribute__(*args):
    56             ...         print("Class getattribute invoked")
    57             ...         return object.__getattribute__(*args)
    58             ...
    59             >>> c = C()
    60             >>> c.__len__()                 # Explicit lookup via instance
    61             Class getattribute invoked
    62             10
    63             >>> type(c).__len__(c)          # Explicit lookup via type
    64             Metaclass getattribute invoked
    65             10
    66             >>> len(c)                      # Implicit lookup
    67             10
    68 
    69     summarize,
    70         '绕过' __getattribute__ 的机制最佳化了解释器的解释速度, 而这种机制是通过对特殊方法的灵活处理
    71         实现的,即特殊方法必须在类对象本身上 set, 而不能通过 monkey patching,再通过 conventional'传统方式' 调用.
    72 
    73         注,
    74             conventional'传统方式' 调用 指的是诸如例子中 len() 跟 __len__() 的对应关系.
    75 
    76     reference,
    77         python doc,
    78             https://docs.python.org/3/reference/datamodel.html#special-lookup
  • 相关阅读:
    Oracle必须要启动的服务
    Oracle_Kill_Session_终极篇
    oracle 修改用户密码
    ORA-01000-超出打开游标的最大数(解决及原因)
    ORA-00600 内部错误代码, 参数 [19004]
    done 多米诺pizza oa 考了spring boot编程
    ebay mettle印度网站oa 切换屏幕就报警
    done摩根史丹利m&t oa
    done peapod 不被太尊重的不面了
    有一点题 virtusa 空口说代码的电面
  • 原文地址:https://www.cnblogs.com/zzyzz/p/7743687.html
Copyright © 2020-2023  润新知