在Python中使用任意属性创建对象的最短方法?

时间:2010-02-17 11:56:19

标签: 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中支持)?

10 个答案:

答案 0 :(得分:22)

使用__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

答案 1 :(得分:22)

type('', (), {})()将创建一个可以具有任意属性的对象。

示例:

obj = type('', (), {})()
obj.hello = "hello"
obj.world = "world"
print obj.hello, obj.world #will print "hello world"
带有三个参数的

type()会创建一个新类型。

第一个参数''是新类型的名称。我们不关心这个名字,所以我们把它留空了。

第二个参数()是基类型的元组,这里是object(隐式)。

第三个参数是新对象的属性字典 - 我们再也不关心它是一个空字典{}

最后,我们在最后用()实例化这个新类型的新实例。

答案 2 :(得分:16)

使用collections.namedtuple

效果很好。

from collections import namedtuple
Data = namedtuple( 'Data', [ 'do_good_stuff', 'do_bad_stuff' ] )
options = Data( True, False )

答案 3 :(得分:13)

这适用于2.5,2.6和3.1:

class Struct(object):
    pass

something = Struct()
something.awesome = abs

result = something.awesome(-42)

编辑: 我想也许给消息来源也会有所帮助。 http://docs.python.org/tutorial/classes.html#odds-and-ends

编辑: 添加了对结果的分配,因为我使用交互式解释器来验证,而您可能不是。

答案 4 :(得分:10)

这是我所知道的最短路

>>> obj = type("myobj",(object,),dict(foo=1,bar=2))
>>> obj.foo
1
>>> obj.bar
2
>>> 

使用dict代替{}确保您的属性名称有效

>>> obj = type("myobj",(object,),{"foo-attr":1,"bar-attr":2})
>>> obj.foo-attr
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'myobj' has no attribute 'foo'
>>>

答案 5 :(得分:6)

使用lambda和type build-in之间的组合,我认为这是最小的方法:

obj = lambda **kwargs: type('obj', (object,), kwargs)()

options = obj(do_good_stuff=True, do_bad_stuff=False)

print options.do_good_stuff
print options.do_bad_stuff

答案 6 :(得分:4)

如果您不需要在构造函数中传递值,则可以执行以下操作:

class data: pass

data.foo = 1
data.bar = 2

使用类静态成员变量来保存数据。

答案 7 :(得分:0)

如果我理解你的问题,你需要记录。 Python类可以这样使用,这就是你所做的。

我相信处理“记录”的最pythonic方式就是...... 词典!类是类固醇的一种字典。

您的类示例data本质上是一种将字典转换为类的方法。

(旁注,我宁愿使用self.__setattr__(name, kw[name])。)

答案 8 :(得分:0)

您可能对“Struct”感兴趣,它是IPython包的一部分。它通过许多有用的方法做你想做的事。

http://ipython.org/ipython-doc/rel-0.13/api/generated/IPython.utils.ipstruct.html

答案 9 :(得分:0)

这通常是你要使用dict的东西,而不是根本不用。