Python语言问题:object()与Function的属性比较
在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__
,我们尽力支持小型、专用的“值”类型。