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.attr1
, obj.a.attr2
, obj.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.namedtuple
, typing.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!')