在 Python 中创建具有任意属性的对象的最短方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2280334/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Shortest way of creating an object with arbitrary attributes in Python?
提问by Blixt
Hey, I just started wondering about this as I came upon a code that expected an object with a certain set of attributes (but with no specification of what type this object should be).
嘿,我刚开始想知道这个,因为我遇到了一个代码,该代码期望一个具有特定属性集的对象(但没有指定该对象应该是什么类型)。
One solution would be to create a new class that has the attributes the code expects, but as I call other code that also needs objects with (other) attributes, I'd have to create more and more classes.
一种解决方案是创建一个具有代码期望属性的新类,但是当我调用其他代码也需要具有(其他)属性的对象时,我必须创建越来越多的类。
A shorter solution is to create a generic class, and then set the attributes on instances of it (for those who thought of using an instance of object
instead of creating a new class, that won't work since object
instances don't allow new attributes).
一个更短的解决方案是创建一个通用类,然后在它的实例上设置属性(对于那些想使用 的实例object
而不是创建新类的人来说,这是行不通的,因为object
实例不允许新属性) .
The last, shortest solution I came up with was to create a class with a constructor that takes keyword arguments, just like the dict
constructor, and then sets them as attributes:
我想出的最后一个最短的解决方案是创建一个带有构造函数的类,它接受关键字参数,就像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)
But I can't help feeling like I've missed something obvious... Isn't there a built-in way to do this (preferably supported in Python 2.5)?
但我不禁觉得我错过了一些明显的东西......难道没有内置的方法来做到这一点(最好在 Python 2.5 中支持)?
采纳答案by Dave Kirby
The original code can be streamlined a little by using __dict__
:
可以使用以下方法简化原始代码__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
In Python 3.3 and greater, this syntax is made available by the types.SimpleNamespace
class.
在 Python 3.3 及更高版本中,此语法由types.SimpleNamespace
类提供。
回答by data
type('', (), {})()
will create an object that can have arbitrary attributes.
type('', (), {})()
将创建一个可以具有任意属性的对象。
Example:
例子:
obj = type('', (), {})()
obj.hello = "hello"
obj.world = "world"
print obj.hello, obj.world #will print "hello world"
type()
with three arguments creates a new type.
type()
使用三个参数创建一个新类型。
The first argument ''
is the name of the new type. We don't care about the name, so we leave it empty.
第一个参数''
是新类型的名称。我们不关心名字,所以我们把它留空。
The second argument ()
is a tuple of base types, here object
(implicit).
第二个参数()
是一个基本类型的元组,这里是object
(隐式)。
The third argument is a dictionary of attributes of the new object - again we don't care to it's an empty dictionary {}
第三个参数是新对象的属性字典 - 我们再次不在乎它是一个空字典 {}
And in the end we instantiate a new instance of this new type with ()
at the end.
最后,我们在末尾实例化这个新类型的一个新实例()
。
回答by S.Lott
Use collections.namedtuple
.
使用collections.namedtuple
.
It works well.
它运作良好。
from collections import namedtuple
Data = namedtuple( 'Data', [ 'do_good_stuff', 'do_bad_stuff' ] )
options = Data( True, False )
回答by Tom Willis
This is the shortest way I know
这是我知道的最短路径
>>> obj = type("myobj",(object,),dict(foo=1,bar=2))
>>> obj.foo
1
>>> obj.bar
2
>>>
using dict instead of {} insures your attribute names are valid
使用 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'
>>>
回答by Tom Willis
This works in 2.5, 2.6, and 3.1:
这适用于 2.5、2.6 和 3.1:
class Struct(object):
pass
something = Struct()
something.awesome = abs
result = something.awesome(-42)
EDIT: I thought maybe giving the source would help out as well. http://docs.python.org/tutorial/classes.html#odds-and-ends
编辑:我认为也许提供来源也会有所帮助。 http://docs.python.org/tutorial/classes.html#odds-and-ends
EDIT: Added assignment to result, as I was using the interactive interpreters to verify, and you might not be.
编辑:为结果添加了分配,因为我正在使用交互式解释器进行验证,而您可能不是。
回答by Tim Richardson
A function is an object. So you could assign attributes to a function. Or make one. This is the simplest way in terms of lines of code, I think.
函数是一个对象。因此,您可以为函数分配属性。或者做一个。我认为,就代码行而言,这是最简单的方法。
def hello():
pass
hello.chook = 123
but the easiest and most elegant way (but Python 3.3+) is to use the standard libary's SimpleNamespace
:
但最简单和最优雅的方法(但 Python 3.3+)是使用标准库的SimpleNamespace
:
>>> from types import SimpleNamespace
>>> foo = SimpleNamespace()
>>> foo.hello = "world"
回答by andrefsp
Use a combination between lambda and type build-in, I think is the smallest way to do that:
使用 lambda 和内置类型之间的组合,我认为是做到这一点的最小方法:
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
回答by abjennings
If you don't need to pass values in the constructor, you can do this:
如果您不需要在构造函数中传递值,您可以这样做:
class data: pass
data.foo = 1
data.bar = 2
You use the class static member variables to hold your data.
您使用类静态成员变量来保存您的数据。
回答by Olivier Verdier
You might be interested in the "Struct", which is part of the IPython package. It does what you want to do, with lots of useful methods.
您可能对“Struct”感兴趣,它是 IPython 包的一部分。它做你想做的事,有很多有用的方法。
http://ipython.org/ipython-doc/rel-0.13/api/generated/IPython.utils.ipstruct.html
http://ipython.org/ipython-doc/rel-0.13/api/generated/IPython.utils.ipstruct.html
回答by Mike Graham
This is typically something you would use a dict for, not making a class at all.
这通常是您会使用 dict 的东西,而不是创建一个类。