python 中的每个类都继承自类“对象”。我想知道“对象”类实现的内部机制。为什么不能为“对象”类分配任何用户属性?我确信它与内存管理有关,但是如果用户想自己实现内存管理怎么办,为什么他不能覆盖 python 中的“对象”类?这是基于我的兴趣并想知道哪些可能没有任何程序化应用程序,但很高兴了解语言本身的内部特征。
3 回答
C 中定义的类型永远不能有用户分配的属性。如果要object
全局替换,则需要遍历存在的每个类,然后替换__builtin__.object
以捕获所有未来的类创建。即使这样也不可靠,因为旧对象可能绑定在其他地方。
这已在 StackOverflow 上进行了讨论,但我无法找到将其链接的讨论。
我想知道的原因是因为我想简化这个例子:
class Box(object):
pass
box = Box()
box.a = "some value"
box.b = 42
在这里,我将box
其用作一种字典,其中键只能是标识符。我这样做是因为写起来box.a
比box["a"]
.
我想这样做:
box = object()
box.a = "some value" # doesn't work
原因是它object
是 Python 中所有对象的根。具有的任何属性object
都必须是任何派生类型。如果要创建包含大量对象的大型列表,则希望它们尽可能小,以免内存不足。所以object
本身是最小的。
编辑:我找到了我想记住的链接:
__slots__
如果我必须从第一原理中推导出推理,我可能会从机制的角度来考虑它。某些类只需要很少的属性,并且属性集对于每个实例总是固定的,因此类似用户属性的“dict”能力的灵活性会浪费cpu(查找动态命名的属性)和空间(空字典的开销,很小但非零),如果有大量实例,这确实会增加很多开销。
当然,这正是__slots__
机制要解决的问题。在对象上为槽中定义的属性分配空间。如果有__dict__
属性,则可以在其中找到非插槽属性,如果没有__dict__
属性,则既不会获得动态属性,也不会获得不需要的 dict 对象(它是实例本身之外的附加堆对象)的成本。
至于为什么object
它本身没有插槽__dict__
,好吧,即使子类表明他们不需要__dict__
插槽,如果他们继承自一个有 的类,那么实例仍然必须有一个__dict__
; 如果object
有一个__dict__
那么绝对每个班级也会付出拥有一个的代价__dict__
,即使他们不需要它。
反而; 除非子类自己定义了类属性,否则子类会获取__dict__
(并且,出于类似的原因)。__weakref__
__slots__
为什么你需要一个普通的实例object
?你只需要一袋属性吗?那么使用dict
. 如果您确实需要某种具有行为和属性的对象,那么无论如何您都在创建子类。
我能想象使用object()
, 而不是 , 的子类的唯一原因object
是,当实例的唯一感兴趣的特征是它的身份时。当函数接受参数时会出现这种情况,并且None
应该将其或其他一些明显的哨兵值理解为与默认值不同:
BAR_DEFAULT = object()
def foo(bar=BAR_DEFAULT):
if bar is BAR_DEFAULT:
#...
在这种情况下,您既不需要也不需要实例上的属性object
,