在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)
以这种方式设置属性几乎肯定不是解决问题的最佳方法。 或者:
-
你知道所有的领域应该提前。 在这种情况下,你可以明确地设置所有的属性。 这看起来像
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
要么
-
你不知道所有的领域应该提前。 在这种情况下,您应该将数据存储为字典而不是污染对象名称空间。 属性用于静态访问。 这种情况看起来像
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'