Python __class __()

max*_*uas -1 python types object-model python-3.x python-internals

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

如果我们这样做:

>>> class Foo:
        pass

>>> a = Foo()
>>> a.__class__ == type.__class__(a)
True
Run Code Online (Sandbox Code Playgroud)

所以,我的问题是:

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

Mar*_*ers 7

__class__是一个描述符对象.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__本身,而是依靠设计来生活在对象类型上.

现在,类对象也是可调用对象.这就是你创建实例的方式; 对于给定的类Foo,您可以通过调用它来创建实例,所以Foo().instance.__class__只是对类对象的引用,就像class_obj = Foo创建对类的引用一样.调用类对象会生成一个新实例,无论您使用什么引用它.

最后,type.__class__只是对type()自己的引用:

>>> type.__class__ is type
True
>>> type.__class__
<class 'type'>
>>> type(type)
<class 'type'>
Run Code Online (Sandbox Code Playgroud)

那是因为type它是自己的类型.Python类型系统的父子关系必须停在某个地方,type就是这一点.

在您的示例中,a.__class__是对Foo类的引用.并且type.__class__是相同的对象type,所以你基本上这样做:

Foo == type(a)
Run Code Online (Sandbox Code Playgroud)

这确实是真的,类型aFoo.

  • @LexPodgorny:这不是一种方法,而是一个数据描述符。是的,您可以创建自己的“__class__”数据描述符,例如通过使用具有设置器的属性。 (3认同)
  • 谢谢您的回答。现在,你说:`instance.__class__`将找到并执行`type(instance).__dict__['__class__'].__get__(instance, type(instance))`,但如果这样做:`type(instance).__dict__`不是 **__ class__** 描述符,这让我想到了第一个问题,并假设描述符 **__ class__** 仅存在于对象 **type** 中,并传递给它们的所有实例对象(所有类)。? (2认同)
  • @maxfraguas:抱歉,我让事情变得比我想要的更加混乱。`object.__dict__['__class__']` 是描述符对象;所有类都继承自该类。在整个类层次结构中搜索此类属性(因此 `next(t.__dict__['__class__'] for t in type(instance).__mro__ if '__class__' in t.__dict__).__get__(instance, type(instance)) `。 (2认同)