在Python中创建具有任意属性的对象的最简方法是什么?
嘿,我最近在看一段代码时,突然想到这个问题。那段代码需要一个对象,这个对象有一组特定的属性,但并没有说明这个对象应该是什么类型。
一种解决办法是创建一个新类,这个类包含代码所需要的属性。但是,如果我还要调用其他代码,这些代码需要的对象有不同的属性,那我就得不停地创建新类,麻烦得很。
一个更简洁的办法是创建一个通用类,然后在这个类的实例上设置属性。对于那些想用object
的实例来代替创建新类的人来说,这个方法不行,因为object
的实例不允许添加新的属性。
我想到的最后一个、也是最简短的解决方案是创建一个类,这个类的构造函数可以接收关键字参数,就像dict
的构造函数一样,然后把这些参数设置为属性:
class data:
def __init__(self, **kw):
for name in kw:
setattr(self, name, kw[name])
options = data(do_good_stuff=True, do_bad_stuff=False)
不过我总觉得我可能漏掉了什么明显的东西……难道没有内置的方法可以做到这一点吗(最好是支持Python 2.5)?
11 个回答
22
使用 collections.namedtuple
。
这个方法很好用。
from collections import namedtuple
Data = namedtuple( 'Data', [ 'do_good_stuff', 'do_bad_stuff' ] )
options = Data( True, False )
69
type('', (), {})()
这个代码会创建一个可以随意添加属性的对象。
举个例子:
obj = type('', (), {})()
obj.hello = "hello"
obj.world = "world"
print obj.hello, obj.world # will print "hello world"
type()
这个函数有三个参数,可以用来创建一个新的类型。
第一个参数
''
是新类型的名字。因为我们不在乎这个名字,所以留空了。第二个参数
()
是一个包含基类的元组。在这里,object
是默认的基类。第三个参数是一个字典,用来定义新对象的属性。我们一开始没有任何属性,所以这个字典是空的
{}
。
最后,我们用 ()
来创建这个新类型的一个实例。
33
原来的代码可以通过使用 __dict__
来简化一下:
In [1]: class data:
...: def __init__(self, **kwargs):
...: self.__dict__.update(kwargs)
...:
In [2]: d = data(foo=1, bar=2)
In [3]: d.foo
Out[3]: 1
In [4]: d.bar
Out[4]: 2
在 Python 3.3 及更高版本中,这种语法可以通过 types.SimpleNamespace
类来实现。