基本答案很简单:“是”:普通对象有一个内部字典来存储实例的属性:
class Foo:
pass
f = Foo()
print(f.__dict__)
# {}
它必须是一个字典,因为在 Python 中,您可以在类未定义的实例上分配新属性:
f.a = 1
print(f.__dict__)
# {'a': 1}
使用字典可以快速进行属性查找,但由于数据结构本身存在内存开销。另外,由于不同的实例Foo
可能定义了不同的属性,每个实例可能需要自己的字典:
g = Foo()
print(g.__dict__)
# {}
print(f.__dict_ == g.__dict__)
# False
A namedtuple
不允许在运行时添加属性。一个具体实例namedtuple
因此,可以将其所有属性存储在由所有实例共享的单个实例中。
Given a namedtuple
和一个实例:
Foo = collections.namedtuple("Foo", 'a,b')
f = Foo(1,2)
The namedtuple
-构造函数产生 https://github.com/python/cpython/blob/12083284c54be25abadd85781d36b63731dc1f0c/Lib/collections/__init__.py#L458 a 描述符 https://stackoverflow.com/a/3798882/2722968对于每个字段并将其存储在类中;这里是存储命名属性和元组索引之间的转换的位置。当您访问属性时a
实例f
,属性访问通过此描述符进行路由:
type(Foo.a)
#<class 'property'>