7

python 中的每个类都继承自类“对象”。我想知道“对象”类实现的内部机制。为什么不能为“对象”类分配任何用户属性?我确信它与内存管理有关,但是如果用户想自己实现内存管理怎么办,为什么他不能覆盖 python 中的“对象”类?这是基于我的兴趣并想知道哪些可能没有任何程序化应用程序,但很高兴了解语言本身的内部特征。

4

3 回答 3

3

C 中定义的类型永远不能有用户分配的属性。如果要object全局替换,则需要遍历存在的每个类,然后替换__builtin__.object以捕获所有未来的类创建。即使这样也不可靠,因为旧对象可能绑定在其他地方。

于 2012-04-11T20:44:58.183 回答
3

这已在 StackOverflow 上进行了讨论,但我无法找到将其链接的讨论。

我想知道的原因是因为我想简化这个例子:

class Box(object):
    pass

box = Box()
box.a = "some value"
box.b = 42

在这里,我将box其用作一种字典,其中键只能是标识符。我这样做是因为写起来box.abox["a"].

我想这样做:

box = object()
box.a = "some value"  # doesn't work

原因是它object是 Python 中所有对象的根。具有的任何属性object都必须是任何派生类型。如果要创建包含大量对象的大型列表,则希望它们尽可能小,以免内存不足。所以object本身是最小的。

编辑:我找到了我想记住的链接:

python中的结构对象

于 2012-04-11T21:45:32.993 回答
1

__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

于 2012-04-11T22:06:35.663 回答