269

Suppose I have a python object x and a string s, how do I set the attribute s on x? So:

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

What's the magic? The goal of this, incidentally, is to cache calls to x.__getattr__().

martineau
  • 119,623
  • 25
  • 170
  • 301
Nick
  • 21,555
  • 18
  • 47
  • 50

5 Answers5

372
setattr(x, attr, 'magic')

For help on it:

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

However, you should note that you can't do that to a "pure" instance of object. But it is likely you have a simple subclass of object where it will work fine. I would strongly urge the O.P. to never make instances of object like that.

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Ali Afshar
  • 40,967
  • 12
  • 95
  • 109
  • 12
    Careful, however, this doesn't work in your scenario where you're creating an instance of object(). – S.Lott Nov 12 '08 at 19:42
  • 4
    Absolutely right, it doesn't. I conveniently ignored that. I would strongly urge the O.P. to never make instances of object like that. – Ali Afshar Nov 12 '08 at 19:44
  • 3
    Damn shame it doesn't work in all cases, as that would be really useful, for example, for adding the `dirty` attribute to user input... – brice Feb 28 '12 at 18:32
  • 1
    @Brice: setattr works in almost all cases. For efficiency and other reasons, 'object' is programmed so that you cannot add extra attributes to it. You can do this with your own class with the `__slots__` attribute. – dirkjot Mar 21 '12 at 22:10
  • 4
    This does not work on `int` as well. Can you explain why? (is it on all `__builtin__`'s? – Jens Timmerman Sep 05 '12 at 15:59
  • 1
    @JensTimmerman: Practically speaking, because integers are supposed to be immutable. The implementation [interns](https://en.wikipedia.org/wiki/String_interning) small integers, strings, and some other builtin immutable types. If you were allowed to set arbitrary attributes on those types, this interning would break in a variety of subtle and confusing ways. – Kevin Oct 10 '16 at 23:47
  • One should be able to subclass `int` using the `type(cls, (int,), kwargs)` pattern? (I subclass `float` on a regular basis and override `__init__` in the custom float to add custom attributes) – cowbert Dec 12 '17 at 21:35
62

Usually, we define classes for this.

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

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

However, you can, to an extent, do this with the setattr and getattr built-in functions. However, they don't work on instances of object directly.

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

They do, however, work on all kinds of simple classes.

class YClass( object ):
    pass

y= YClass()
setattr( y, 'myAttr', 'magic' )
y.myAttr
Vincenzooo
  • 2,013
  • 1
  • 19
  • 33
S.Lott
  • 384,516
  • 81
  • 508
  • 779
23

let x be an object then you can do it two ways

x.attr_name = s 
setattr(x, 'attr_name', s)
vijay shanker
  • 2,517
  • 1
  • 24
  • 37
2

Also works fine within a class:

def update_property(self, property, value):
   setattr(self, property, value)
d.raev
  • 9,216
  • 8
  • 58
  • 79
-2

If you want a filename from an argument:

import sys

filename = sys.argv[1]

file = open(filename, 'r')

contents = file.read()

If you want an argument to show on your terminal (using print()):

import sys

arg = sys.argv[1]

arg1config = print(arg1config)
Cassova
  • 530
  • 1
  • 3
  • 20
Coder100
  • 1
  • 1
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 29 '22 at 22:43