除了为了正确性而绕过任何实例属性之外,隐式特殊方法查找通常也会绕过
__getattribute__()
方法,甚至是对象的元类。
The docs提及__hash__
,__repr__
和__len__
等特殊方法,我从经验中了解到它还包含{2.7}的__iter__
。
引用an answer to a related question:
"魔术
__methods__()
被特别对待:他们被内部分配到"插槽"在类型数据结构中加速查找,只在这些插槽中查找。"
为了改善我对another question的回答,我需要知道:具体来说,我们在谈论哪些方法?
答案 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
然后我还试图通过getattr
和hasattr
- &gt;获取每个名称。同样的结果。每次都会调用__getattribute__
。
所以,如果有人有其他想法......我太懒了,不能在C代码中查看,但我确定答案就在那里。
所以,要么是某些东西我没有做对,要么文档在说谎。