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
  • 相关阅读:
    CSS浏览器兼容问题大全
    JavaScript游戏之飞机接子弹
    Html5小游戏之变大的小球
    JavaScript游戏之小型打飞机
    JavaScript游戏之是男人就飞10000米
    JavaScript无聊打地鼠
    JavaScript游戏之优化篇
    前端开发的开始基于OO的Ajax类
    JavaScript游戏之仿劲舞团(简陋版)
    仿JQuery的show与hide动画函数
  • 原文地址:https://www.cnblogs.com/zzyzz/p/7743687.html
Copyright © 2011-2022 走看看