Python __init__ setattr on arguments?

mk12 picture mk12 · Sep 14, 2009 · Viewed 8.5k times · Source

It seems that often __init__ methods are similar to this:

def __init__(self, ivar1, ivar2, ivar3):
    self.ivar1 = ivar1
    self.ivar2 = ivar2
    self.ivar3 = ivar3

Is there someway to turn the arguments into a list (without resorting to *args or **kwargs) and then using setattr to set the instance variables, with the name of the parameter and the argument passed? And maybe slice the list, e.g. you'd need to at least slice it to [1:] because you don't want self.self.

(actually I guess it would need to be a dictionary to hold the name and value)

like this:

def __init__(self, ivar1, ivar2, ivar3, optional=False):
    for k, v in makedict(self.__class__.__init__.__args__): # made up __args__
        setattr(self, k, v)

Thanks!

Responding to Unknown's answer, I found this to work:

Class A(object):
    def __init__(self, length, width, x):
        self.__dict__.update(dict([(k, v) for k, v in locals().iteritems() if k != 'self']))

or

Class A(object):
    def __init__(self, length, width, x):
        self.__dict__.update(locals())
        del self.__dict__['self']

Not too bad..

Answer

Unknown picture Unknown · Sep 14, 2009

Here you go. Yes this is an ugly evil hack. Yes the object needs a __dict__ variable. But hey, its a neat little one liner!

def __init__(self):
    self.__dict__.update(locals())

The constructor can take any type of arguments.

class test(object):
    def __init__(self, a, b, foo, bar=5)...

a = test(1,2,3)
dir(a)

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'foo', 'bar', 'self']

It will also include self, but you can easily delete that or make your own update function that ignores self.