我想在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”类的实例上设置属性。


当前回答

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

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

其他回答

这些解决方案在测试期间非常有用。基于其他人的答案,我在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

有几种方法可以达到这个目标。 基本上你需要一个可扩展的对象。

obj.a = type('Test', (object,), {})  
obj.a.b = 'fun'  

obj.b = lambda:None

class Test:
  pass
obj.c = Test()

正如医生所说:

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

你可以使用伪类实例。

您正在使用哪些对象?刚刚尝试了一个样例类,它工作得很好:

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。

更新:从评论这是一个重复:为什么你不能添加属性的对象在python?

有不同的类型。Python 3.3+中的SimpleNamespace类:

obj = someobject
obj.a = SimpleNamespace()
for p in params:
    setattr(obj.a, p, value)
# obj.a.attr1

collections.namedtuple,打字。NamedTuple可用于不可变对象。PEP 557—数据类建议一个可变的替代方案。

要获得更丰富的功能,可以尝试attrs包。参见示例用法。Pydantic可能也值得一看。