Python语言问题:object()与Function的属性比较

17 投票
4 回答
1450 浏览
提问于 2025-04-15 12:37

在Python中,像这样给一个对象实例添加新的属性是非法的:

>>> a = object()
>>> a.hhh = 1

会抛出错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'hhh'

不过,对于一个函数对象来说,这样做是可以的。

>>> def f():
...   return 1
...
>>> f.hhh = 1

那么,这种差异背后的原因是什么呢?

4 个回答

1

这里的意思是,object()这个实例其实是一个特殊的例子。它“是”一个对象,但本身并不是为了单独使用而设计的。

可以把object看作是一个临时的解决办法,用来连接旧式的类型和类。在Python 3.0中,它将逐渐被遗忘,因为不再作为

class Foo( object ):
    pass

f = Foo()
f.randomAttribute = 3.1415926
7

Alex Martelli给你的问题提供了一个很棒的答案。如果你想在一个空对象上添加任意属性,可以这样做:

class myobject(object):
    pass

o = myobject()
o.anything = 123

如果你已经知道要添加的属性,下面的方法会更高效(而且文档也更清晰):

class myobject(object):
    __slots__ = ('anything', 'anythingelse')

o = myobject()
o.anything = 123
o.anythingelse = 456
22

函数对象之所以可以支持任意属性,是因为在我们添加这个功能之前,有些框架(比如解析器生成器)在滥用函数的文档字符串(还有其他函数对象的属性)来存储每个函数的重要信息。这样的需求通过实例证明了,直接在语言中支持任意命名属性比让文档字符串被滥用要好得多,这一点是显而易见的。

为了支持任意的实例属性,一个类型必须为它的每个实例提供一个 __dict__。对函数来说,这没什么大不了的(反正函数本身就不是小对象),但对于其他一些本来就打算做成小对象的类型来说,这可能就比较麻烦了。为了尽可能让 object 类型变得轻量,同时提供 __slots__ 以避免在 object 的子类型中使用每个实例的 __dict__,我们尽力支持小型、专用的“值”类型。

撰写回答