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

я импортирую из 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's 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 должно быть достаточно.)

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

6 ответов


можно использовать 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

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

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


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

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

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

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

вы также можете использовать 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

использование именованных кортежей (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

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


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

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