在尝试实现对象包装器时,我偶然发现了python中的奇怪行为。请考虑以下代码(我已经从我遇到的案例中简化了它以展示其基础知识):
class A(object):
def hello(self):
print "hello ",
class B(object):
def __init__(self, obj):
self.obj = obj
def __getattr__(self, attr):
return getattr(self.obj, attr)
def regular_func(self, attr):
return getattr(self.obj, attr)
a=A()
b=B(a)
for x in xrange(10):
print id(b.hello), ",",
print
for x in xrange(10):
print id(a.hello), ",",
print
for x in xrange(10):
print id(A.hello), ",",
print
for x in xrange(10):
print id(b.regular_func("hello")), ",",
print
for x in xrange(10):
b.hello()
上述脚本的输出将是:
4375335072 , 4375100144 , 4375335072 , 4375100144 , 4375335072 , 4375100144 , 4375335072 , 4375100144 , 4375335072 , 4375100144 ,
4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 ,
4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 ,
4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 , 4375100144 ,
hello hello hello hello hello hello hello hello hello hello
注意每当调用__getattr__
(第一行打印)时,id如何在两个值之间切换?我已经搞砸了一下,这也发生在__getattribute__
上,但请注意,在调用regular_func
时它永远不会发生。它总是在两个值之间切换,并且总是切换(而不是随机)。
即使我将__getattr__
更改为:
a=A()
class B(object):
def __getattr__(self, attr):
return getattr(a, attr)
或者这样:
a=A()
class B(object):
def __getattr__(self, attr):
return a.__getattribute__(attr)
在上面的例子中,重复打印id(a.__getattribute__("hello"))
总是给出相同的数字。
任何人都可以解释这种奇特的行为,或建议任何进一步的想法来调查吗?