Действительно ли возможно создать объект из словаря в Python таким способом, которым каждый ключ является атрибутом того объекта?
Что-то вроде этого:
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])
Обновление
Как предлагает Брент Нэш, вы можете сделать это более гибким, разрешив также аргументы ключевого слова:
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)
Вы можете получить доступ к атрибутам объекта с помощью __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 Employee (object):
def __init __ (self, name, last_name, age):
self.name = name
self.last_name = last_name
self.age = age
d = {'name': 'Оскар', 'last_name': 'Reyes', 'age': 32}
e = Сотрудник (** d)
напечатайте e.name # Oscar
напечатайте e.age + 10 # 42
или
Вы не знаю, какие поля должны быть заранее. В этом случае вы должны хранить данные как dict вместо того, чтобы загрязнять пространство имен объектов. Атрибуты предназначены для статического доступа. Этот случай будет выглядеть так:
class Employee (object):
def __init __ (self, data):
self.data = data
d = { 'name': 'Оскар', 'last_name': 'Reyes', 'age': 32}
e = Сотрудник (d)
распечатать e.data ['name '] # Oscar
print e.data [' age '] + 10 # 42
Другое решение, которое в основном эквивалентно случаю 1, - использовать collections. namedtuple
. См. Ответ Ван, чтобы узнать, как это реализовать.
Я думаю, что ответ с использованием 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()
для доступа ко всем свойствам как к словарю, но вы не можете добавить дополнительные атрибуты позже, только во время построения.