Bog*_* M. 11 python python-3.x
我试图填补我对 Python 对象和类如何工作的理解上的空白。
裸object
实例不支持以任何方式分配属性:
> object().a = 5
# or
> setattr(object(), 'a', 5)
AttributeError: 'object' object has no attribute 'a'
Run Code Online (Sandbox Code Playgroud)
我认为这是因为裸object
实例不具有__dict__
属性:
> '__dict__' in dir(object())
False
Run Code Online (Sandbox Code Playgroud)
然而,裸object
实例确实有一个定义的__setattr__
属性,所以这对我来说有点令人困惑:
> '__setattr__' in dir(object())
True
Run Code Online (Sandbox Code Playgroud)
另一方面,常规空类的实例具有属性分配的全部能力:
class B(object):
pass
> B().a = 5
> setattr(B(), 'a', 5)
Run Code Online (Sandbox Code Playgroud)
我的问题是:如果直接继承的话object
,实例和class B(object)
实例之间有什么内在区别允许后者具有可分配的属性?B
object
类object()
就像 Python 宇宙的基本粒子,是 Python 中所有对象(读取所有内容)的基类(或构建块)。因此,所述行为是合乎逻辑的,因为并非所有对象都可以(或应该)设置任意属性。例如,如果一个对象可以设置属性,那么它就没有意义NoneType
,并且就像一样object()
,None
对象也没有__dict__
属性。事实上,两者唯一的区别是None
对象具有__bool__
属性。例如:
n = None\no = object()\n\ntype(n)\n>>> <class \'NoneType\'>\n\nset(dir(n)) - set(dir(o))\n>>> {\'__bool__\'}\n\nisinstance(n, object)\n>>> True\n\nbool(n)\n>>> False\n
Run Code Online (Sandbox Code Playgroud)\n继承object
是自动的,并且就像任何其他继承方式一样,可以向子级添加自己的类方法和属性。正如您已经展示的那样, Python 自动添加__dict__
自定义数据类型的属性。
简而言之,__dict__
对于没有自定义可写属性(即NoneType
)的对象,添加对象的属性比删除它要容易得多。
根据评论更新:
\n原评论:
\n\n\n那么可以安全地假设它是
\n__setattr__
检查是否存在__dict__
并相应地引发异常吗?\xe2\x80\x93\nbool3max
在CPython中,背后的逻辑object.__setattr__(self, name, value)
是由Objects/object.c实现的_PyObject_GenericSetAttrWithDict
(参见CPython源代码)。具体来说,如果name
参数是字符串,则检查该对象__dict__
在其插槽之一中是否有对象,并确保它已“准备好”(请参阅这一行)。
对象的就绪状态由 确定PyType_Ready()
,简要描述并引用自此处:
\n\n在 C 中定义 Python 类型涉及使用您关心的值填充 PyTypeObject 结构的字段。我们将每个字段称为 \xe2\x80\x9cslot\xe2\x80\x9d。
\n定义准备就绪后,我们将其传递给 PyType_Ready() 函数,该函数会执行许多操作,包括将大部分类型定义暴露给 Python\xe2\x80\x99s 属性查找机制。
\n