哪种特殊方法在Python中绕过__getattribute__?

时间:2012-10-13 11:33:05

标签: python magic-methods

  

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

The docs提及__hash____repr____len__等特殊方法,我从经验中了解到它还包含{2.7}的__iter__

引用an answer to a related question

  

"魔术__methods__()被特别对待:他们被内部分配到"插槽"在类型数据结构中加速查找,只在这些插槽中查找。"

为了改善我对another question的回答,我需要知道:具体来说,我们在谈论哪些方法?

2 个答案:

答案 0 :(得分:4)

您可以在object.__getattribute__的python3 documentation中找到答案,其中说明:

  

无条件调用以实现类实例的属性访问。如果该类还定义了__getattr__(),那么   除非__getattribute__()调用后者,否则不会调用后者   显式或引发AttributeError。这个方法应该返回   (计算)属性值或引发AttributeError异常。在   为了避免在这个方法中无限递归,它的实现   应该始终调用具有相同名称的基类方法来访问   它需要的任何属性,例如,object。__getattribute__(self, name)

     

注意

     

当查找特殊方法作为通过语言语法或内置的隐式调用的结果时,仍然可以绕过此方法   功能。请参阅特殊方法查找。

同样this页面也解释了这个“机器”的工作原理。只有当您使用__getattribute__(点)运算符(以及Zagorulkin指出的.访问属性时)才会调用基本hasattr

请注意,该页面未指定隐式查找哪些特殊方法,因此我认为这适用于所有这些方法(您可能会发现here

答案 1 :(得分:2)

签入2.7.9

使用__getattribute__object上找到的任何神奇方法找不到任何绕过type来电的方法:

# 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

然后我还试图通过getattrhasattr - &gt;获取每个名称。同样的结果。每次都会调用__getattribute__

所以,如果有人有其他想法......我太懒了,不能在C代码中查看,但我确定答案就在那里。

所以,要么是某些东西我没有做对,要么文档在说谎。