11

除了为了正确性而绕过任何实例属性之外,隐式特殊方法查找通常也会绕过__getattribute__()对象元类的方法。

文档提到了特殊方法,例如__hash__,__repr____len__, 我从经验中知道它还包括__iter__Python 2.7。

引用相关问题的答案

“魔法__methods__()被特殊对待:它们被内部分配到类型数据结构中的“槽”以加快它们的查找速度,并且只在这些槽中查找它们。

为了改进我对另一个问题的回答,我需要知道:具体来说,我们在谈论哪些方法?

4

2 回答 2

4

您可以在 python3文档中找到答案object.__getattribute__,其中指出:

无条件调用以实现类实例的属性访问。如果该类还定义了__getattr__(),则不会调用后者,除非__getattribute__()显式调用它或引发 AttributeError。此方法应返回(计算的)属性值或引发 AttributeError 异常。为了避免这个方法的无限递归,它的实现应该总是调用同名的基类方法来访问它需要的任何属性,例如对象。__getattribute__(self, name).

笔记

由于通过语言语法或内置函数隐式调用而查找特殊方法时,仍可能绕过此方法。请参阅特殊方法查找。

这个页面也准确地解释了这个“机器”是如何工作的。从根本上说__getattribute__,仅当您使用(点)运算符访问属性时才调用.(也hasattr如 Zagorulkin 指出的那样)。

请注意,该页面未指定隐式查找哪些特殊方法,因此我认为这适用于所有方法(您可以在此处找到。

于 2012-10-25T07:36:59.370 回答
2

签入 2.7.9

找不到任何绕过对 的调用的方法,使用在or__getattribute__上找到的任何神奇方法:objecttype

# Preparation step: did this from the console
# magics = set(dir(object) + dir(type))
# got 38 names, for each of the names, wrote a.<that_name> to a file
# Ended up with this:

a.__module__
a.__base__
#...

把它放在那个文件的开头,我把它重命名为一个合适的python模块(asdf.py)

global_counter = 0

class Counter(object):
    def __getattribute__(self, name):
        # this will count how many times the method was called
        global global_counter
        global_counter += 1
        return super(Counter, self).__getattribute__(name)

a = Counter()
# after this comes the list of 38 attribute accessess
a.__module__
#...
a.__repr__
#...

print global_counter  # you're not gonna like it... it printer 38

然后我还尝试通过getattrand hasattr-> 相同的结果来获取每个名称。__getattribute__每次都被调用。

因此,如果有人有其他想法……我懒得去查看 C 代码,但我确信答案就在某个地方。

所以要么是我做的不对,要么是文档在撒谎。

于 2015-01-05T01:09:39.257 回答