J'importe d'un fichier CSV et je reçois des données à peu près au format
{ 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 }
Les noms des champs sont dynamiques. (Eh bien, ils sont dynamiques dans la mesure où il pourrait y avoir plus que Field1 et Field2, mais je sais que Field1
et Field2
seront toujours présents.
J'aimerais pouvoir transmettre ce dictionnaire à ma classe allMyFields
afin de pouvoir accéder aux données ci-dessus en tant que propriétés.
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
Aucune suggestion? En ce qui concerne la raison, j'aimerais pouvoir tirer parti des conseils de code, et importer les données dans un dictionnaire appelé data
, comme je l'ai déjà fait, ne me le permet pas.
(Comme les noms de variables ne sont pas résolus avant l'exécution, je vais toujours devoir lancer un os à Komodo - je pense que le self.Field1 = None
devrait suffire.)
Alors, comment puis-je faire ce que je veux? Ou suis-je en train d'aboyer un arbre mal conçu, non-python?
Vous pouvez utiliser setattr
(attention cependant: chaque chaîne n'est pas un nom d'attribut valide!):
>>> 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: laissez-moi vous expliquer la différence entre le code ci-dessus et la réponse de SilentGhost . L'extrait de code ci-dessus crée une classe dont attributs d'instance est basé sur un dictionnaire. Le code de SilentGhost crée une classe dont les attributs de classe sont basés sur un dictionnaire donné.
Selon votre situation spécifique, l’une ou l’autre de ces solutions peut être plus appropriée. Êtes-vous en train de créer une ou plusieurs instances de classe? Si la réponse est un, vous pouvez également ignorer la création d'objet et ne construire que le type (et aller ainsi avec la réponse de SilentGhost).
>>> q = { 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 }
>>> q = type('allMyFields', (object,), q)
>>> q.Field1
3000
docs for type
explique bien ce qui se passe ici (voir utilisation en tant que constructeur).
edit: si vous avez besoin de variables d'instance, ceci fonctionne aussi:
>>> a = q() # first instance
>>> a.Field1
3000
>>> a.Field1 = 1
>>> a.Field1
1
>>> q().Field1 # second instance
3000
Vous pouvez également utiliser dict.update
au lieu de boucler manuellement sur items
(et si vous faites une boucle, iteritems
est préférable).
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
Utilisation de tuples nommés (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
Vous pouvez 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({ 'Field1' : 3000, 'Field2' : 6000, 'RandomField' : 5000 })
print q.Field1
print q.Field2
print q.RandomField
Si vous essayez de rechercher un attribut que dict
a déjà (disons keys
ou get
), vous aurez cet attribut de classe dict
(une méthode). Si la clé demandée n'existe pas dans la classe dict
, la méthode __getattr__
sera appelée et effectuera votre recherche de clé.
Utilisez setattr pour la belle façon. Le moyen le plus rapide est de 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
>>>
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__)