是否可以通过python中的字典创建对象,使得每个键都是该对象的属性?
像这样:
d = { 'name': 'Oscar', 'lastName': 'Reyes', 'age':32 }
e = Employee(d)
print e.name # Oscar
print e.age + 10 # 42
我认为这与该问题几乎完全相反:来自对象字段的Python字典
是否可以通过python中的字典创建对象,使得每个键都是该对象的属性?
像这样:
d = { 'name': 'Oscar', 'lastName': 'Reyes', 'age':32 }
e = Employee(d)
print e.name # Oscar
print e.age + 10 # 42
我认为这与该问题几乎完全相反:来自对象字段的Python字典
Answers:
当然,是这样的:
class Employee(object):
def __init__(self, initial_data):
for key in initial_data:
setattr(self, key, initial_data[key])
更新资料
正如布伦特·纳什(Brent Nash)所建议的,您还可以通过允许使用关键字参数来使其更加灵活:
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)
Employee(some_dict)
和Employee(**some_dict)
API是不一致的。应该提供哪个更好。
()
而不是None
,则可以这样做:def __init__(self, iterable=(), **kwargs): self.__dict__.update(iterable, **kwargs)
。
[[setattr(self,key,d[key]) for key in d] for d in some_dict]
AddressNotFoundError
的错误(在这种情况下,返回正确的数据,而不是炸毁)-我发疯了,在PHP((object) ['x' => 'y']
)中如此简单的操作在Python中需要大量的工作
以这种方式设置属性几乎肯定不是解决问题的最佳方法。要么:
您知道所有字段都应该提前。在这种情况下,您可以显式设置所有属性。这看起来像
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
要么
您不知道所有字段都应该提前。在这种情况下,您应该将数据存储为dict,而不是污染对象名称空间。这些属性用于静态访问。这种情况看起来像
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基本等效的另一种解决方案是使用collections.namedtuple
。有关如何实现的信息,请参见van的答案。
您可以使用访问对象的属性__dict__
,并对其调用update方法:
>>> 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
__dict__
是一个实现工件,不应使用。同样,这忽略了类中描述符的存在。
__dict__
是语言的文档部分,而不是实现工件。
setattr
优于__dict__
直接访问。您必须牢记很多事情,这些事情可能会导致__dict__
您在使用时不在那里或不做自己想要做的事情__dict__
,但setattr
实际上与实际要做的事情相同foo.bar = baz
。
__dict__
建议不要使用:docs.python.org/tutorial/classes.html#id2
为什么不只使用属性名称作为字典的键?
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存储类中使用的一个技巧)
我认为,settattr
如果您确实需要支持,那么使用答案是可行的方法dict
。
但是,如果Employee
object只是可以使用点语法(.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()
将所有属性作为字典访问的方法,但是以后只能在构造过程中才能添加其他属性。
def __init__(self,**initial_data)
时获得了一个额外的好处,那就是拥有一个也可以执行关键字参数的init方法(例如“ e = Employee(name ='Oscar')”)或仅接受字典(例如“ e = Employee( **字典)“)。