我一直认为在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__
属性来标识参数的类型,是吗?它是否为此目的使用了一些“更可靠”的来源?如果是这样,我们可以直接访问吗?
答案 0 :(得分:4)
x.__class__
和type(x)
不相同。
type(x)
根植于typeobject.c,并会返回真实类型ob_type
。
/ *特殊情况:类型(x)应返回x-&gt; ob_type * /
虽然x.__class__
只是一个属性查找。它等同于object.__getattribute__(x, '__class__')
,除非重新定义了属性查找
object
的{{1}}是一个数据描述符,也在typeobject.c中定义。其getter也会返回'__class__'
。因此,在大多数情况下,ob_type
和x.__class__
会返回相同的内容。
但是type(x)
,即weakproxy
,故意定义了自己的proxy_getattr
。这就是为什么_PyWeakref_ProxyType
与您的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)
在此示例中均为true。由于isinstance(c, C)
会首先检查isinstance
的相等性。