我可以像这样创建一个python对象
class Test:
pass
t1 = Test()
t1.var = "value"
t1.num = 100
并且可以使用
查看对象的字典print(t1.__dict__)
# prints
{'var': 'value', 'num': 100}
这是否意味着python对象在内部存储为字典?
答案 0 :(得分:1)
没有。但在内部,所有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
要理解为什么所有允许动态设置变量,方法和其他信息的类在内部使用dicts存储此信息,我们需要考虑哪些词典非常擅长:O(1)
使用O(1)
信息访问插入和删除。由于解释器不知道类可能具有哪些属性,如果该属性是变量,方法等,直到运行时,这需要在运行时使用绑定到类的某种容器。在其他语言中,如C ++,这是使用函数指针数组(通常,虽然不能保证)或虚拟表实现的,允许您动态地将一组预定义的方法更改为类。但是,由于方法名称已经过加密编码,因此不允许向类中动态添加或删除方法。除了散列映射或二进制搜索树之外的任何方法都可能无法有效地允许动态类型化。
大多数情况下,是的。最佳,没有。使用__slots__
可以最小化类的大小。