Набор атрибутов из словаря в python
можно ли создать объект из словаря в Python таким образом, что каждый ключ является атрибутом объекта?
что-то вроде этого:
d = { 'name': 'Oscar', 'lastName': 'Reyes', 'age':32 }
e = Employee(d)
print e.name # Oscar
print e.age + 10 # 42
Я думаю, что это было бы в значительной степени обратным этому вопросу:словарь Python из полей объекта
7 ответов:
конечно, что-то вроде этого:
class Employee(object): def __init__(self, initial_data): for key in initial_data: setattr(self, key, initial_data[key])обновление
как предлагает Брент Нэш, вы можете сделать это более гибким, разрешив аргументы ключевых слов:
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или
вы не знаете, что все поля должны быть впереди времени. В этом случае вы должны хранить данные как 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. См. ответ Вана о том, как это реализовать.
Вы можете получить доступ к атрибутам объекта с
__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
почему бы просто не использовать имена атрибутов в качестве ключа в словарь?
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объект-это просто структура, к которой вы можете получить доступ с помощью синтаксиса dot (.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()метод для доступа ко всем свойствам в виде словаря, но вы не может добавить дополнительные атрибуты позже, только во время строительство.
например
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)
подобно использованию dict, вы можете просто использовать 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'
Comments