我想在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 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
>>> 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']

你可以使用我古老的Bunch方法,但如果你不想创建一个“Bunch类”,Python中已经存在一个非常简单的方法——所有函数都可以有任意属性(包括lambda函数)。因此,以下工作:

obj = someobject
obj.a = lambda: None
setattr(obj.a, 'somefield', 'somevalue')

与古老的Bunch食谱相比,是否失去清晰度是可以的,这是一个风格上的决定,当然,我将留给你。

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

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?

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

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

obj.b = lambda:None

class Test:
  pass
obj.c = Test()

如果你正在寻找链赋值,要做的事情,如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'}

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