在Python中创建具有任意属性的对象的最简方法是什么?

54 投票
11 回答
29601 浏览
提问于 2025-04-15 19:23

嘿,我最近在看一段代码时,突然想到这个问题。那段代码需要一个对象,这个对象有一组特定的属性,但并没有说明这个对象应该是什么类型。

一种解决办法是创建一个新类,这个类包含代码所需要的属性。但是,如果我还要调用其他代码,这些代码需要的对象有不同的属性,那我就得不停地创建新类,麻烦得很。

一个更简洁的办法是创建一个通用类,然后在这个类的实例上设置属性。对于那些想用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 类来实现。

撰写回答