简单解释
不是。但是在内部,所有Python对象(除了那些使用__slots__
或Python内置对象的对象)都使用字典进行动态属性访问。
如下例所示,使用__slots__
可以使类型不存储内部字典,从而防止动态设置方法、字段或其他信息到类型中。不过,这会导致类型的大小减小。
In [7]: class A:
...: __slots__ = ('fields')
...: def __init__(self):
...: self.fields = 1
...:
In [9]: dir(A)
Out[9]:
['__class__',
'__delattr__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__slots__',
'__str__',
'__subclasshook__',
'fields']
如果你查看CPython源代码
code,你会发现大多数内置类型也没有被存储为字典:
#ifndef Py_LIMITED_API
typedef struct {
PyObject_HEAD
double ob_fval;
} PyFloatObject;
#endif
目的
为了理解为什么所有允许动态设置变量、方法和其他信息的类在内部使用字典来存储这些信息,我们需要考虑字典非常擅长的事情:O(1)的信息访问和O(1)的插入和删除。由于解释器在运行时不知道类可能具有哪些属性,如果该属性是变量、方法等,这就需要使用某种容器绑定到类的运行时。在其他语言(如C++)中,这通过使用函数指针数组(通常,但不保证),或虚拟表来实现,允许您动态地将预定义的一组方法更改为类。然而,由于方法名已经硬编码,这不允许动态添加或删除方法到类。除哈希映射或二叉搜索树之外的任何方法都可能无法有效地允许动态类型。
tldr
大多数情况下是可以的。但最好使用__slots__
来最小化类的大小。