我想在Python中创建一个动态对象(在另一个对象内),然后为其添加属性。
我试过了:
obj = someobject
obj.a = object()
setattr(obj.a, 'somefield', 'somevalue')
但这不起作用。
有什么想法吗?
编辑:
我从for
循环设置属性,循环遍历值列表,例如
params = ['attr1', 'attr2', 'attr3']
obj = someobject
obj.a = object()
for p in params:
obj.a.p # where p comes from for loop variable
在上面的例子中,我会得到obj.a.attr1
,obj.a.attr2
,obj.a.attr3
。
我使用了setattr
函数,因为我不知道如何从obj.a.NAME
循环中执行for
。
如何根据上例中的p
值设置属性?
答案 0 :(得分:289)
内置object
可以实例化,但不能在其上设置任何属性。 (我希望它可以,出于这个目的。)它没有__dict__
来保存属性。
我通常只是这样做:
class Object(object):
pass
a = Object()
a.somefield = somevalue
如果可以的话,我会给Object
类提供一个更有意义的名称,具体取决于我放入的数据类型。
有些人做了不同的事情,他们使用dict
的子类,允许属性访问获取键。 (d.key
代替d['key']
)
修改:要添加问题,请使用setattr
。您无法在setattr
个实例上使用object()
。
params = ['attr1', 'attr2', 'attr3']
for p in params:
setattr(obj.a, p, value)
答案 1 :(得分:181)
你可以使用我古老的Bunch食谱,但如果你不想制作一个“束类”,Python中已经存在一个非常简单的 - 所有函数都可以有任意属性(包括lambda函数) )。因此,以下工作:
obj = someobject
obj.a = lambda: None
setattr(obj.a, 'somefield', 'somevalue')
与古老的Bunch
食谱相比,失去清晰度是否合适,是一种风格决定,我当然会留给你。
答案 2 :(得分:31)
有几种方法可以实现这一目标。 基本上你需要一个可扩展的对象。
obj.a = type('Test', (object,), {})
obj.a.b = 'fun'
obj.b = lambda:None
class Test:
pass
obj.c = Test()
答案 3 :(得分:18)
基本上是mock
模块。
import mock
obj = mock.Mock()
obj.a = 5
答案 4 :(得分:17)
现在你可以做(不确定它是否和evilpie一样):
MyObject = type('MyObject', (object,), {})
obj = MyObject()
obj.value = 42
答案 5 :(得分:12)
尝试以下代码:
$ python
>>> class Container(object):
... pass
...
>>> x = Container()
>>> x.a = 10
>>> x.b = 20
>>> x.banana = 100
>>> x.a, x.b, x.banana
(10, 20, 100)
>>> dir(x)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__',
'__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'banana']
答案 6 :(得分:8)
您也可以直接使用类对象;它创建了一个命名空间:
class a: pass
a.somefield1 = 'somevalue1'
setattr(a, 'somefield2', 'somevalue2')
答案 7 :(得分:7)
答案 8 :(得分:2)
这些解决方案在测试过程中非常有用。基于其他人的答案我在Python 2.7.9中这样做(没有staticmethod我得到一个TypeError(未绑定的方法......):
In [11]: auth = type('', (), {})
In [12]: auth.func = staticmethod(lambda i: i * 2)
In [13]: auth.func(2)
Out[13]: 4
答案 9 :(得分:1)
您使用的是哪些对象?刚尝试使用示例类,它运行良好:
class MyClass:
i = 123456
def f(self):
return "hello world"
b = MyClass()
b.c = MyClass()
setattr(b.c, 'test', 123)
b.c.test
我得到123
作为答案。
我看到这种失败的唯一情况是你在内置对象上尝试setattr
。
答案 10 :(得分:0)
今天晚些时候到了这里,但是我的pennyworth有一个对象恰好在应用程序中保留了一些有用的路径但你可以调整它以适应任何你想要使用getattr访问的信息分类的地方和点符号(这是我认为这个问题的真正含义):
import os
def x_path(path_name):
return getattr(x_path, path_name)
x_path.root = '/home/x'
for name in ['repository', 'caches', 'projects']:
setattr(x_path, name, os.path.join(x_path.root, name))
这很酷,因为现在:
In [1]: x_path.projects
Out[1]: '/home/x/projects'
In [2]: x_path('caches')
Out[2]: '/home/x/caches'
所以这会像上面的答案那样使用函数对象,但是使用函数来获取值(如果你愿意的话,你仍然可以使用(getattr, x_path, 'repository')
而不是x_path('repository')
。)
答案 11 :(得分:0)
如果我们可以在创建嵌套对象之前确定所有属性和值并将它们聚合在一起,那么我们可以创建一个新类,该类在创建时采用字典参数。
# python 2.7
class NestedObject():
def __init__(self, initial_attrs):
for key in initial_attrs:
setattr(self, key, initial_attrs[key])
obj = someobject
attributes = { 'attr1': 'val1', 'attr2': 'val2', 'attr3': 'val3' }
obj.a = NestedObject(attributes)
>>> obj.a.attr1
'val1'
>>> obj.a.attr2
'val2'
>>> obj.a.attr3
'val3'
我们还可以允许关键字参数。参见this post。
class NestedObject(object):
def __init__(self, *initial_attrs, **kwargs):
for dictionary in initial_attrs:
for key in dictionary:
setattr(self, key, dictionary[key])
for key in kwargs:
setattr(self, key, kwargs[key])
obj.a = NestedObject(attr1='val1', attr2='val2', attr3= 'val3')
答案 12 :(得分:0)
我认为最简单的方法是通过collections模块。
import collections
FinanceCtaCteM = collections.namedtuple('FinanceCtaCte', 'forma_pago doc_pago get_total')
def get_total(): return 98989898
financtacteobj = FinanceCtaCteM(forma_pago='CONTADO', doc_pago='EFECTIVO',
get_total=get_total)
print financtacteobj.get_total()
print financtacteobj.forma_pago
print financtacteobj.doc_pago
答案 13 :(得分:0)
问题 - 为什么不改用字典?
obj = { "a": { "somefield" : "somevalue" } }
答案 14 :(得分:-1)
di = {}
for x in range(20):
name = '_id%s' % x
di[name] = type(name, (object), {})
setattr(di[name], "attr", "value")
答案 15 :(得分:-2)
我这样看的其他方式:
import maya.cmds
def getData(objets=None, attrs=None):
di = {}
for obj in objets:
name = str(obj)
di[name]=[]
for at in attrs:
di[name].append(cmds.getAttr(name+'.'+at)[0])
return di
acns=cmds.ls('L_vest_*_',type='aimConstraint')
attrs=['offset','aimVector','upVector','worldUpVector']
getData(acns,attrs)