3

我一直相信在 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标识yset.

type显示“真实”类型 - weakproxy。所以,type不使用__class__属性来识别参数的类型,是吗?它是否为此目的使用了一些“更可靠”的来源?如果是这样,我们可以直接访问它吗?

4

1 回答 1

4

x.__class__并且type(x)不等价。 type(x)植根于typeobject.c,并将返回真正的类型ob_type

/* 特殊情况:type(x) 应该返回 x->ob_type */

虽然x.__class__只是一个属性查找。它等效于object.__getattribute__(x, '__class__'),除非已重新定义属性查找。
object's'__class__'是一个数据描述符,它也在typeobject.c中定义。它的吸气剂也返回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会检查 first 的相等性ob_type

于 2013-03-25T22:54:57.113 回答