Подтвердить что ты не робот

Создание свойств экземпляра класса из словаря?

Я импортирую из CSV и получаю данные примерно в формате

{ 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 }

Имена полей являются динамическими. (Ну, они динамичны в том, что может быть больше Field1 и Field2, но я знаю, что Field1 и Field2 всегда будут там.

Я бы хотел пропустить этот словарь в моем классе allMyFields, чтобы я мог обращаться к вышеуказанным данным как к свойствам.

class allMyFields:
    # I think I need to include these to allow hinting in Komodo. I think.
    self.Field1 = None
    self.Field2 = None

    def __init__(self,dictionary):
        for k,v in dictionary.items():
            self.k = v
            #of course, this doesn't work. I've ended up doing this instead
            #self.data[k] = v
            #but it not the way I want to access the data.

q = { 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 }
instance = allMyFields(q)
# Ideally I could do this.
print q.Field1

Любые предложения? Что касается причин - я хотел бы иметь возможность воспользоваться подсказкой кода и импортировать данные в словарь под названием data, как я это делал, не дает мне ничего такого.

(Поскольку имена переменных не разрешены до времени выполнения, мне все равно придется бросать кость в Комодо - я думаю, что self.Field1 = None должно быть достаточно.)

Итак - как мне сделать то, что я хочу? Или я лаяю плохо спроектированное дерево без питона?

4b9b3361

Ответ 1

Вы можете использовать setattr (будьте осторожны: не каждая строка является допустимым именем атрибута!):

>>> class AllMyFields:
...     def __init__(self, dictionary):
...         for k, v in dictionary.items():
...             setattr(self, k, v)
... 
>>> o = AllMyFields({'a': 1, 'b': 2})
>>> o.a
1

Изменить: позвольте мне объяснить разницу между приведенным выше кодом и SilentGhost answer. Вышеприведенный фрагмент кода создает класс атрибутов экземпляра на основе данного словаря. Код SilentGhost создает класс, атрибуты класса которого основаны на данном словаре.

В зависимости от конкретной ситуации любое из этих решений может быть более подходящим. Вы просто создаете один или несколько экземпляров класса? Если ответ один, вы можете полностью пропустить создание объекта и только построить его тип (и, следовательно, пойти с ответом SilentGhost).

Ответ 2

>>> q = { 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 }
>>> q = type('allMyFields', (object,), q)
>>> q.Field1
3000

docs для type хорошо объясняют, что происходит здесь (см. использование в качестве конструктора).

edit: в случае, если вам нужны переменные экземпляра, также работает следующее:

>>> a = q()             # first instance
>>> a.Field1
3000
>>> a.Field1 = 1
>>> a.Field1
1
>>> q().Field1           # second instance
3000

Ответ 3

Вы также можете использовать dict.update вместо ручного циклирования по items (и если вы выполняете цикл, iteritems лучше).

class allMyFields(object):
    # note: you cannot (and don't have to) use self here
    Field1 = None
    Field2 = None

    def __init__(self, dictionary):
        self.__dict__.update(dictionary)

q = { 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 }
instance = allMyFields(q)

print instance.Field1      # => 3000
print instance.Field2      # => 6000
print instance.RandomField # => 5000

Ответ 4

Использование именованных кортежей (Python 2.6):

>>> from collections import namedtuple

>>> the_dict = {'Field1': 3, 'Field2': 'b', 'foo': 4.9}
>>> fields = ' '.join(the_dict.keys())
>>> AllMyFields = namedtuple('AllMyFields', fields)
>>> instance = AllMyFields(**the_dict)

>>> print instance.Field1, instance.Field2, instance.foo
3 b 4.9

Ответ 5

Вы можете создать подкласс dict, который позволяет искать атрибуты для ключей:

class AttributeDict(dict):
    def __getattr__(self, name):
        return self[name]

q = AttributeDict({ 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 })
print q.Field1              
print q.Field2              
print q.RandomField

Если вы попытаетесь найти атрибут, который dict уже имеет (скажем keys или get), вы получите атрибут класса dict (метод). Если запрашиваемый ключ не существует в классе dict, тогда метод __getattr__ будет вызван и будет выполнять поиск по ключевым словам.

Ответ 6

Используйте setattr для красивого пути. Быстрый n-грязный способ - обновить внутренний словарь экземпляра:

>>> class A(object):
...    pass
...
>>> a = A()
>>> a.__dict__.update({"foo": 1, "bar": 2})
>>> a.foo
1
>>> a.bar
2
>>>

Ответ 7

class SomeClass:
    def __init__(self,
                 property1,
                 property2):
       self.property1 = property1
       self.property2 = property2


property_dict = {'property1': 'value1',
                 'property2': 'value2'}
sc = SomeClass(**property_dict)
print(sc.__dict__)

Ответ 8

Или вы можете попробовать это

class AllMyFields:
    def __init__(self, field1, field2, random_field):
        self.field1 = field1
        self.field2 = field2
        self.random_field = random_field

    @classmethod
    def get_instance(cls, d: dict):
        return cls(**d)


a = AllMyFields.get_instance({'field1': 3000, 'field2': 6000, 'random_field': 5000})
print(a.field1)

Ответ 9

улучшен подкласс dict

повторение dict работает!

class AttributeDict(dict):
    """/info/149123/creating-class-instance-properties-from-a-dictionary/871747#871747"""

    def __getattr__(self, name):
        return self[name] if not isinstance(self[name], dict) \
            else AttributeDict(self[name])


if __name__ == '__main__':
    d = {"hello": 1, "world": 2, "cat": {"dog": 5}}
    d = AttributeDict(d)
    print(d.cat)
    print(d.cat.dog)
    print(d.cat.items())

    """
    {'dog': 5}
    5
    dict_items([('dog', 5)])
    """