我一直相信在 Python 解释器中 x.__class__
和 type(x)
的值是等价的。但是,如果我们执行以下操作(在 Python 2.7、3.3 以及 PyPy 2.0b1 中):
>>> import weakref
>>> x = set()
>>> y = weakref.proxy(x)
>>> x.__class__, isinstance(x, set), type(x)
(<type 'set'>, True, <type 'set'>)
>>> y.__class__, isinstance(y, set), type(y)
(<type 'set'>, True, <type 'weakproxy'>)
我们将看到 y.__class__
对应于 weakref.proxy
的包装类型(我想 weakref.proxy
只是替换伪装的属性)。甚至 isinstance
也将 y
标识为 set
。
但是 type
显示“真实”类型 -- weakproxy
。所以,type
不使用 __class__
属性来标识参数的类型,对吗?它是否为此目的使用了一些“更可靠”的来源?如果是这样,我们可以直接访问它吗?
最佳答案
x.__class__
和 type(x)
不等价。
type(x)
Root 于 typeobject.c , 并将返回真实类型 ob_type
。
/* Special case: type(x) should return x->ob_type */
虽然 x.__class__
只是一个属性查找。它等效于 object.__getattribute__(x, '__class__')
,除非属性查找已被重新定义。
object
的'__class__'
是一个数据描述符,在typeobject.c中也有定义.它的getter也返回 ob_type
。因此,在大多数情况下,x.__class__
和 type(x)
返回相同的东西。
但是weakproxy
,即_PyWeakref_ProxyType
,故意定义了自己的proxy_getattr
.这就是为什么 y.__class__
与您的情况下的 type(y)
不同。
在下面的实验中,我们可以达到同样的效果。
class A(object):
pass
class C(object):
def __getattribute__(self, name):
if name == '__class__':
return A
return object.__getattribute__(self, name)
>>> c = C()
>>> c.__class__
<class '__main__.A'>
>>> type(c)
<class '__main__.C'>
此外,isinstance(c, A)
和 isinstance(c, C)
在这个例子中都是真的。因为 isinstance
会先检查 ob_type
是否相等。
关于python - 弱引用类型的行为 - 无法理解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15624948/