Python __class __()

时间:2018-01-02 18:50:25

标签: python python-3.x types python-internals object-model

在Python的文档中,__class__被描述为属性。在对象type(元类)中,__class__似乎是一种方法。

如果我们这样做:

>>> class Foo:
        pass

>>> a = Foo()
>>> a.__class__ == type.__class__(a)
True

所以,我的问题是:

  1. 当我们致电a.__class__时,我们是否真的在调用方法type.__class__(a)
  2. 这是__class__不是__dict__的{​​{1}}属性成员的原因吗?

1 个答案:

答案 0 :(得分:6)

__class__descriptor object。 Python核心对象上的许多属性都是作为描述符实现的。您应该将其视为实现细节,仅此而已。

__class__是一个描述符,因为Python需要能够验证您为其分配的新值;分配给__class__需要遵守的某些限制,并且使__class__描述符是最有效的方法。

当您尝试访问对象上的属性时,会自动在该类型上找到并调用描述符对象。 instance.__class__将在类上找到并执行__class__描述符(通过搜索继承图中的所有类),通常以object.__dict__['__class__'].__get__(instance, type(instance))结尾(其中object通常是在__class__序列中找到type(instance).__mro__属性的第一个类;这是因为Python总是使用类型的__getattribute__方法来查找属性,并且该方法知道如何处理在类和基础上找到的描述符,以及查看object.__dict__属性。因此,他们不会依赖于对象__dict__本身,而是按照设计生活在对象类型上。

现在,类对象也是 callable 对象。这就是你如何创建一个实例;对于给定的类Foo,您可以通过调用它来创建实例,因此Foo()instance.__class__只是对类对象的引用,就像class_obj = Foo将创建对类的引用一样。调用类对象会产生一个新实例,无论你用它来获取它的任何引用。

最后,type.__class__只是对type()本身的引用:

>>> type.__class__ is type
True
>>> type.__class__
<class 'type'>
>>> type(type)
<class 'type'>

那是因为type是它自己的类型。必须在某处停止Python类型系统的父子关系,type就是这一点。

在您的示例中,a.__class__是对Foo类的引用。 type.__class__type是同一个对象,因此您基本上就是这样做了:

Foo == type(a)

确实如此,a的类型为Foo