Создание свойств экземпляра класса из словаря?
Вопрос
Я импортирую из 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
то, чем я занимался до сих пор, не позволяет мне ничего из этого.
(Поскольку имена переменных не разрешаются до времени выполнения, мне все равно придется бросить кость Komodo - я думаю, что self.Field1 = None
этого должно быть достаточно.)
Итак, как мне сделать то, что я хочу?Или я поднимаю плохо спроектированное дерево, не относящееся к python?
Решение
Вы можете использовать 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 от 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
атрибут класса (метод).Если запрашиваемый вами ключ не существует на dict
класс, затем __getattr__
будет вызван метод, который выполнит поиск вашего ключа.
Используйте setattr для красивого способа.Самый быстрый способ - обновить внутренний словарь экземпляра:
>>> class A(object):
... pass
...
>>> a = A()
>>> a.__dict__.update({"foo": 1, "bar": 2})
>>> a.foo
1
>>> a.bar
2
>>>
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__)
Или вы можете попробовать это
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)