Набор приписывает из словаря в Python

Действительно ли возможно создать объект из словаря в Python таким способом, которым каждый ключ является атрибутом того объекта?

Что-то вроде этого:

 d = { 'name': 'Oscar', 'lastName': 'Reyes', 'age':32 }

 e = Employee(d) 
 print e.name # Oscar 
 print e.age + 10 # 42 

Я думаю, что это была бы в значительной степени инверсия этого вопроса: словарь Python от полей объекта

89
задан smci 13 November 2017 в 18:34
поделиться

4 ответа

Конечно, что-то вроде этого:

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)
148
ответ дан 24 November 2019 в 07:13
поделиться

Вы можете получить доступ к атрибутам объекта с помощью __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
13
ответ дан 24 November 2019 в 07:13
поделиться

Такая установка атрибутов почти наверняка не лучший способ решить проблему. Либо:

  1. Вы знаете, что все поля должны быть впереди времени. В этом случае вы можете явно установить все атрибуты. Это будет выглядеть так:

     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 
     

    или

  2. Вы не знаю, какие поля должны быть заранее. В этом случае вы должны хранить данные как 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 . См. Ответ Ван, чтобы узнать, как это реализовать.

40
ответ дан 24 November 2019 в 07:13
поделиться

Я думаю, что ответ с использованием 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() для доступа ко всем свойствам как к словарю, но вы не можете добавить дополнительные атрибуты позже, только во время построения.

6
ответ дан 24 November 2019 в 07:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: