我想在Python中创建一个动态对象(在另一个对象内部),然后向其添加属性。

我试着:

obj = someobject
obj.a = object()
setattr(obj.a, 'somefield', 'somevalue')

但这并不奏效。

什么好主意吗?

编辑:

我设置的属性从一个循环通过一个值的列表,例如。

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函数,因为我不知道如何从for循环中执行obj.a.NAME。

如何根据上面例子中的p值设置属性?


有关为什么它不起作用的详细信息,请参见不能在“object”类的实例上设置属性。


当前回答

这些解决方案在测试期间非常有用。基于其他人的答案,我在Python 2.7.9中这样做(没有staticmethod,我得到一个TypeError (unbound method…):

In [11]: auth = type('', (), {})
In [12]: auth.func = staticmethod(lambda i: i * 2)
In [13]: auth.func(2)
Out[13]: 4

其他回答

内置对象可以被实例化,但不能在其上设置任何属性。(为了这个目的,我希望它可以。)它没有__dict__来保存属性。

我通常是这样做的:

class Object(object):
    pass

a = Object()
a.somefield = somevalue

当我可以时,我给Object类起一个更有意义的名字,这取决于我在其中放入什么样的数据。

有些人做了不同的事情,他们使用dict的子类,允许属性访问来获得键。(d.key而不是d['key'])

编辑:对于您的问题,使用setattr是很好的。你不能在object()实例上使用setattr。

params = ['attr1', 'attr2', 'attr3']
for p in params:
    setattr(obj.a, p, value)

你也可以直接使用类对象;它创建了一个命名空间:

class a: pass
a.somefield1 = 'somevalue1'
setattr(a, 'somefield2', 'somevalue2')

如果你正在寻找链赋值,要做的事情,如django模型模板抽象属性赋值:

from types import SimpleNamespace


def assign(target, *args, suffix):
    ls = target
    for i in range(len(args) - 1):
        a = args[i]
        ns = SimpleNamespace()
        setattr(ls, a, ns)
        ls = ns
    setattr(ls, args[-1], suffix)
    return ls


a = SimpleNamespace()
assign(a, 'a', 'b', 'c', suffix={'name': 'james'})
print(a.a.b.c)
# {'name': 'james'}

它允许您传递模型作为目标,并分配结束属性给它。

我认为最简单的方法是通过集合模块。

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

正如医生所说:

注意:object没有__dict__对象,因此不能将任意属性赋给object类的实例。

你可以使用伪类实例。