100 votes

Créer des propriétés d'instance de classe à partir d'un dictionnaire ?

Je suis en train d'importer à partir d'un fichier CSV et d'obtenir des données approximativement sous le format

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

Les noms des champs sont dynamiques. (Eh bien, ils sont dynamiques en ce sens qu'il pourrait y avoir plus que Field1 et Field2, mais je sais que Field1 et Field2 seront toujours là.

J'aimerais pouvoir passer ce dictionnaire dans ma classe allMyFields pour que je puisse accéder aux données ci-dessus en tant que propriétés.

classe allMyFields:
    # Je pense que j'ai besoin d'inclure cela pour permettre l'indication dans Komodo. Je pense.
    self.Field1 = None
    self.Field2 = None

    def __init__(self,dictionary):
        pour k,v in dictionary.items():
            self.k = v
            #bien sûr, cela ne fonctionne pas. J'ai fini par faire cela à la place
            #self.data[k] = v
            #mais ce n'est pas la façon dont je veux accéder aux données.

q = { 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 }
instance = allMyFields(q)
# Idéalement je pourrais faire ceci.
print q.Field1

Des suggestions? En ce qui concerne pourquoi -- j'aimerais pouvoir profiter de l'indication de code, et l'importation des données dans un dictionnaire appelé data comme je l'ai fait jusqu'à présent ne me le permet pas.

(Puisque les noms de variables ne sont résolus qu'au moment de l'exécution, je vais quand même devoir filer un os à Komodo - je pense que le self.Field1 = None devrait suffire.)

Alors - comment puis-je faire ce que je veux? Ou est-ce que je pigeonne un arbre mal conçu, non-python?

151voto

Stephan202 Points 27707

Vous pouvez utiliser setattr (mais faites attention : chaque chaîne n'est pas un nom d'attribut valide!) :

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

Édition : laissez-moi vous expliquer la différence entre le code ci-dessus et la réponse de SilentGhost. Le fragment de code ci-dessus crée une classe dont les attributs d'instance sont basés sur un dictionnaire donné. Le code de SilentGhost crée une classe dont les attributs de classe sont basés sur un dictionnaire donné.

En fonction de votre situation spécifique, l'une ou l'autre de ces solutions peut être plus adaptée. Prévoyez-vous de créer une ou plusieurs instances de classe ? Si la réponse est une, vous pouvez également sauter complètement la création d'objet et ne construire que le type (et donc opter pour la réponse de SilentGhost).

43voto

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

docs for type explain well what's going here (see use as a constructor).

edit: in case you need instance variables, the following also works:

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

20voto

Cat Plus Plus Points 53385

Vous pouvez également utiliser dict.update au lieu de parcourir manuellement les items (et si vous parcourez, iteritems est mieux).

class allMyFields(object):
    # note: vous ne pouvez pas (et vous n'êtes pas obligé de) utiliser self ici
    Field1 = None
    Field2 = None

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

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

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

9voto

Matt Anderson Points 7461

Vous pourriez créer une sous-classe de dict qui permet la recherche d'attributs pour les clés :

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

q = AttributeDict({ 'Champ1' : 3000, 'Champ2' : 6000, 'ChampAléatoire' : 5000 })
print q.Champ1              
print q.Champ2              
print q.ChampAléatoire

Si vous essayez de rechercher un attribut que la classe dict possède déjà (comme keys ou get), vous obtiendrez cet attribut de classe dict (une méthode). Si la clé demandée n'existe pas dans la classe dict, alors la méthode __getattr__ sera appelée et effectuera votre recherche de clé.

6voto

truppo Points 10346

Utilisez setattr pour la manière propre. La manière rapide et sale consiste à mettre à jour le dictionnaire interne de l'instance :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X