zoukankan      html  css  js  c++  java
  • 对特殊方法的访问

     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
  • 相关阅读:
    当前信息型强人工智能发展缺失条件--规则
    假象篇(1)-动态可变参数的神经网络
    02梦断代码阅读笔记
    结队开发之NABCD
    01梦断代码阅读笔记
    03构建之法阅读笔记
    进度3
    02构建之法阅读笔记
    01构建之法阅读笔记
    关于最大子序和的算法问题(二)
  • 原文地址:https://www.cnblogs.com/zzyzz/p/7743687.html
Copyright © 2011-2022 走看看