Pergunta

Eu estou importando de um arquivo CSV e obtenção de dados mais ou menos no formato

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

Os nomes dos campos são dinâmicos. (Bem, eles são dinâmicos em que pode haver mais de Field1 e Field2, mas sei Field1 e Field2 são sempre vai estar lá.

Eu gostaria de ser capaz de passar neste dicionário em meu allMyFields classe para que eu possa acessar os dados acima como propriedades.

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

Todas as sugestões? Tanto quanto isso -. Eu gostaria de ser capaz de tirar proveito de dicas de código, e importar os dados em um dicionário chamado data como tenho vindo a fazer não me pagar nada disso

(Uma vez que os nomes de variáveis ??não são resolvidos até tempo de execução, estou ainda vai ter que jogar um osso para Komodo -. Eu acho que o self.Field1 = None deve ser suficiente)

Assim - como eu faço o que eu quero? Ou eu sou latindo um mal projetado árvore, não-python?

Foi útil?

Solução

Você pode usar setattr (ter cuidado, porém: não cada corda é um nome de atributo válido):

>>> 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

Editar: deixe-me explicar a diferença entre o código acima e o SilentGhost resposta . O trecho de código acima cria uma classe de que atributos da instância são baseados em um determinado dicionário. código de SilentGhost cria uma classe cujos atributos class são baseados em um determinado dicionário.

Dependendo da sua situação específica qualquer uma destas soluções pode ser mais adequada. Você simples para criar uma ou mais instâncias de classe? Se a resposta é uma só, assim como você pode ignorar a criação de objeto inteiramente e só construir o tipo (e, portanto, ir com a resposta de SilentGhost).

Outras dicas

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

docs para type explicar bem o que está acontecendo aqui (veja o uso como um construtor ).

editar : caso você precisa variáveis ??de instância, o também seguintes obras:

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

Você também pode usar dict.update em vez de loop manualmente sobre items (e se você estiver looping, iteritems é melhor).

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

Usando tuplas nomeadas (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

Você poderia fazer uma subclasse de dict que permite acessar atributos para as chaves:

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

Se você tentar olhar para cima um atributo que dict já tem (keys dizer ou get), você vai ter que atributo de classe dict (um método). Se a chave que você pedir para não existe na classe dict, então o método __getattr__ será chamado e vai fazer sua pesquisa de chave.

Use setattr pela maneira bonita. A maneira rápida-n-sujo é atualizar o dicionário interno exemplo:

>>> 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__)

Ou você pode tentar este

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)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top