Python:创build对象并为其添加属性

我想在Python中创build一个dynamic对象(在另一个对象内),然后给它添加属性。

我试过了:

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.ap # where p comes from for loop variable 

在上面的例子中,我会得到obj.a.attr1obj.a.attr2obj.a.attr3

我使用了setattr函数,因为我不知道如何从for循环执行obj.a.NAME

在上面的例子中,我将如何设置基于p值的属性?

你可以使用我的古老的Bunch配方,但是如果你不想创build一个“束类”,那么Python中已经存在一个非常简单的类 – 所有的函数都可以有任意的属性(包括lambda函数)。 所以,下面的作品:

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

与古老的Bunch配方相比,是否失去了清晰度是一个风格决定,我当然会留给你。

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

我通常只是这样做:

 class Object(object): pass a = Object() a.somefield = somevalue 

当我可以的时候,我会给这个Object类一个更有意义的名字,这取决于我放入的数据types。

有些人做了一个不同的事情,他们在那里使用一个dict的子类,允许属性访问得到的关键。 ( d.key而不是d['key']

编辑 :除了你的问题,使用setattr是好的。 你不能在object()实例上使用setattr

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

在Python 3.3+中有types.SimpleNamespace类 :

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

collections.namedtupletyping.NamedTuple可以用于不可变的对象。 PEP 557 – 数据类提出了一个可变的替代scheme。

为了更丰富的function,你可以尝试attrs包 。 看到一个示例用法 。

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

 obj.a = type('Test', (object,), {}) obj.ab = 'fun' obj.b = lambda:None class Test: pass obj.c = Test() 

现在你可以做(​​不知道它是否与邪恶的答案相同):

 MyObject = type('MyObject', (object,), {}) obj = MyObject() obj.value = 42 

试试下面的代码:

 $ python >>> class Container(object): ... pass ... >>> x = Container() >>> xa = 10 >>> xb = 20 >>> x.banana = 100 >>> xa, xb, 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'] 

正如文档所说 :

注意object没有__dict__ ,所以你不能将任意属性赋值给object类的实例。

你可以使用虚拟类实例。

mock模块基本上是为了这个。

 import mock obj = mock.Mock() obj.a = 5 

这些解决scheme在testing中非常有帮助。 build立在其他人的答案我这样做在Python 2.7.9(没有staticmethod我得到一个TypeError(unbound方法…):

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

你使用哪个对象? 刚刚尝试过一个示例类,它工作正常:

 class MyClass: i = 123456 def f(self): return "hello world" b = MyClass() bc = MyClass() setattr(bc, 'test', 123) bctest 

我得到了123作为答案。

我看到这个失败的唯一情况是如果你正在尝试一个内build对象的setattr

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

 di = {} for x in range(20): name = '_id%s' % x di[name] = type(name, (object), {}) setattr(di[name], "attr", "value") 

在这一天晚些时候,但这里是我的pennyworth与一个对象,恰好在应用程序中保存了一些有用的path,但你可以适应任何你想要的信息,你可以通过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')您仍然可以使用(getattr, x_path, 'repository')而不是x_path('repository') )。

其他方式我看,这样:

 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) 

这些都在文档中 。

TLDR:你需要声明模拟的return_value属性,其余的是'Magic'。

例:

 SomeConstructor = MagicMock() SomeConstructor.return_value. \ some_class_method.assert_called_once_with('cool!') SomeConstructor.return_value. \ some_inner_property. \ some_inner_method.assert_called_once_with('super cool!')