¿Cómo establece programáticamente un atributo?

204

Supongamos que tengo un objeto pitón xy una cadena s, ¿cómo se ajusta el atributo sde x? Entonces:

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

Cual es la magia El objetivo de esto, por cierto, es almacenar en caché las llamadas x.__getattr__().

Mella
fuente

Respuestas:

289
setattr(x, attr, 'magic')

Para obtener ayuda:

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

Editar: Sin embargo, debe tener en cuenta (como se señala en un comentario) que no puede hacer eso a una instancia "pura" de object. Pero es probable que tenga una subclase simple de objeto donde funcionará bien. Insto encarecidamente al OP a que nunca haga instancias de objetos como ese.

Ali Afshar
fuente
12
Cuidado, sin embargo, esto no funciona en su escenario donde está creando una instancia de object ().
S.Lott
3
Absolutamente correcto, no lo hace. Convenientemente ignoré eso. Insto encarecidamente al OP a que nunca haga instancias de objetos como ese.
Ali Afshar
2
Lástima que no funciona en todos los casos, ya que sería muy útil, por ejemplo, para añadir el dirtyatributo a la entrada del usuario ...
Brice
1
@Brice: setattr funciona en casi todos los casos. Por eficiencia y otras razones, 'objeto' está programado para que no pueda agregarle atributos adicionales. Puede hacer esto con su propia clase con el __slots__atributo
dirkjot
44
Esto no funciona inttan bien. ¿Puedes explicar porque? (¿está en todos __builtin__?
Jens Timmerman
53

Por lo general, definimos clases para esto.

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

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

Sin embargo, puede, hasta cierto punto, hacer esto con el setattry getattrfunciones integradas. Sin embargo, no funcionan en instancias de forma objectdirecta.

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

Sin embargo, trabajan en todo tipo de clases simples.

class YClass( object ):
    pass

y= YClass()
setattr( y, 'myAttr', 'magic' )
y.myAttr
S.Lott
fuente
25
¿Alguna idea de por qué esto no funciona con instancias de object ()?
meawoppl
@meawoppl Deberías hacer eso como una nueva pregunta
Tobias Kienzler
Pedido aquí .
jalanb
1
¿Puedo hacer esto con módulos, en lugar de clases?
bonobo
21

deja que x sea un objeto, entonces puedes hacerlo de dos maneras

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