Comment définissez-vous par programmation un attribut?

204

Supposons que j'ai un objet python xet une chaîne s, comment puis-je configurer l'attribut ssur x? Alors:

>>> x = SomeObject()
>>> attr = 'myAttr'
>>> # magic goes here
>>> x.myAttr
'magic'

Quelle est la magie? Le but de ceci, incidemment, est de mettre en cache les appels vers x.__getattr__().

pseudo
la source

Réponses:

289
setattr(x, attr, 'magic')

Pour de l'aide à ce sujet:

>>> help(setattr)
Help on built-in function setattr in module __builtin__:

setattr(...)
    setattr(object, name, value)

    Set a named attribute on an object; setattr(x, 'y', v) is equivalent to
    ``x.y = v''.

Edit: Cependant, vous devez noter (comme indiqué dans un commentaire) que vous ne pouvez pas faire cela à une instance "pure" de object. Mais il est probable que vous ayez une simple sous-classe d'objet où cela fonctionnera bien. J'exhorte fortement l'OP à ne jamais créer d'instances d'objet comme ça.

Ali Afshar
la source
12
Attention, cependant, cela ne fonctionne pas dans votre scénario où vous créez une instance de object ().
S.Lott
3
Tout à fait raison, ce n'est pas le cas. J'ai commodément ignoré cela. J'exhorte fortement l'OP à ne jamais créer d'instances d'objet comme ça.
Ali Afshar
2
Dommage que cela ne fonctionne pas dans tous les cas, car cela serait vraiment utile, par exemple, pour ajouter l' dirtyattribut à l'entrée utilisateur ...
brice
1
@Brice: setattr fonctionne dans presque tous les cas. Pour des raisons d'efficacité et pour d'autres raisons, «objet» est programmé de sorte que vous ne puissiez pas lui ajouter d'attributs supplémentaires. Vous pouvez le faire avec votre propre classe avec l' __slots__attribut.
dirkjot
4
Cela ne fonctionne pas intaussi bien. Pouvez-vous expliquer pourquoi? (est-ce sur tout __builtin__le monde?
Jens Timmerman
53

Habituellement, nous définissons des classes pour cela.

class XClass( object ):
   def __init__( self ):
       self.myAttr= None

x= XClass()
x.myAttr= 'magic'
x.myAttr

Cependant, vous pouvez, dans une certaine mesure, le faire avec les fonctions setattret getattrintégrées. Cependant, ils ne fonctionnent pas sur les instances de objectdirectement.

>>> a= object()
>>> setattr( a, 'hi', 'mom' )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'hi'

Cependant, ils fonctionnent sur toutes sortes de classes simples.

class YClass( object ):
    pass

y= YClass()
setattr( y, 'myAttr', 'magic' )
y.myAttr
S.Lott
la source
25
Avez-vous une idée de pourquoi cela ne fonctionne pas avec les instances de object ()?
meawoppl
@meawoppl Vous devriez poser cette question comme une nouvelle question
Tobias Kienzler
Demandé ici .
jalanb
1
puis-je faire cela avec des modules, au lieu de classes?
bonobo
21

laissez x être un objet, vous pouvez le faire de deux manières

x.attr_name = s 
setattr(x, 'attr_name', s)
vijay shanker
la source