在python中设置字典的属性

是否有可能从一个字典在Python中创build一个对象,使每个键是该对象的属性?

像这样的东西:

d = { 'name': 'Oscar', 'lastName': 'Reyes', 'age':32 } e = Employee(d) print e.name # Oscar print e.age + 10 # 42 

我认为这几乎是这个问题的反面: 来自对象字段的Python字典

当然,这样的事情:

 class Employee(object): def __init__(self, initial_data): for key in initial_data: setattr(self, key, initial_data[key]) 

更新

正如布伦特·纳什(Brent Nash)所build议的那样,通过允许关键字参数,也可以使其更加灵活

 class Employee(object): def __init__(self, *initial_data, **kwargs): for dictionary in initial_data: for key in dictionary: setattr(self, key, dictionary[key]) for key in kwargs: setattr(self, key, kwargs[key]) 

那么你可以这样调用它:

 e = Employee({"name": "abc", "age": 32}) 

或者像这样:

 e = Employee(name="abc", age=32) 

甚至像这样:

 employee_template = {"role": "minion"} e = Employee(employee_template, name="abc", age=32) 

以这种方式设置属性几乎肯定不是解决问题的最佳方法。 或者:

  1. 你知道所有的领域应该提前。 在这种情况下,你可以明确地设置所有的属性。 这看起来像

     class Employee(object): def __init__(self, name, last_name, age): self.name = name self.last_name = last_name self.age = age d = {'name': 'Oscar', 'last_name': 'Reyes', 'age':32 } e = Employee(**d) print e.name # Oscar print e.age + 10 # 42 

    要么

  2. 你不知道所有的领域应该提前。 在这种情况下,您应该将数据存储为字典而不是污染对象名称空间。 属性用于静态访问。 这种情况看起来像

     class Employee(object): def __init__(self, data): self.data = data d = {'name': 'Oscar', 'last_name': 'Reyes', 'age':32 } e = Employee(d) print e.data['name'] # Oscar print e.data['age'] + 10 # 42 

基本上等同于情况1的另一个解决scheme是使用collections.namedtuple 。 请参阅van的回答,了解如何实现这一点。

你可以用__dict__来访问一个对象的属性,并调用它的更新方法:

 >>> class Employee(object): ... def __init__(self, _dict): ... self.__dict__.update(_dict) ... >>> dict = { 'name': 'Oscar', 'lastName': 'Reyes', 'age':32 } >>> e = Employee(dict) >>> e.name 'Oscar' >>> e.age 32 

为什么不使用属性名称作为字典的关键字?

 class StructMyDict(dict): def __getattr__(self, name): try: return self[name] except KeyError as e: raise AttributeError(e) def __setattr__(self, name, value): self[name] = value 

您可以使用命名参数,元组列表或字典或个别属性分配进行初始化,例如:

 nautical = StructMyDict(left = "Port", right = "Starboard") # named args nautical2 = StructMyDict({"left":"Port","right":"Starboard"}) # dictionary nautical3 = StructMyDict([("left","Port"),("right","Starboard")]) # tuples list nautical4 = StructMyDict() # fields TBD nautical4.left = "Port" nautical4.right = "Starboard" for x in [nautical, nautical2, nautical3, nautical4]: print "%s <--> %s" % (x.left,x.right) 

或者,不是提高属性错误,而是为未知值返回None。 (在web2py存储类中使用的一个技巧)

我认为,如果你真的需要支持dict那么使用settattr答案是要走的路。

但是,如果Employee对象只是一个你可以用点语法( .name )而不是dict语法( ['name'] )访问的结构体,那么你可以像这样使用namedtuple :

 from collections import namedtuple Employee = namedtuple('Employee', 'name age') e = Employee('noname01', 6) print e #>> Employee(name='noname01', age=6) # create Employee from dictionary d = {'name': 'noname02', 'age': 7} e = Employee(**d) print e #>> Employee(name='noname02', age=7) print e._asdict() #>> {'age': 7, 'name': 'noname02'} 

你有_asdict()方法来作为字典来访问所有的属性,但是以后只能在构build过程中不能添加其他的属性。

比如说

 class A(): def __init__(self): self.x=7 self.y=8 self.z="name" 

如果你想一次设置属性

 d = {'x':100,'y':300,'z':"blah"} a = A() a.__dict__.update(d) 

类似于使用字典,你可以像这样使用kwargs:

 class Person: def __init__(self, **kwargs): self.properties = kwargs def get_property(self, key): return self.properties.get(key, None) def main(): timmy = Person(color = 'red') print(timmy.get_property('color')) #prints 'red'