4

Possible Duplicate:
Assign function arguments to `self`

Often I have constructors that look like the following:

class Foo(object):
  def __init__(self,a,b,c):
    self.a = a
    self.b = b
    self.c = c

I was wondering if there was a convenient way to encode constructors like this. Perhaps something that looks like:

class Foo(object):
  SOME_MACRO_LIKE_THINGY_THAT_SPECIFIES_THE_CONSTRUCTOR(a,b,c)

that would behave exactly like the original code above.

What bugs me with the original version is that I have to write each instance variable of Foo three times (once as an argument, once as self.a and once again as the value to assign to self.a).

I suppose it's not that big a deal, but I feel like the code would look neater with less repetition.

What is the Pythonic way to handle this situation?

Community
  • 1
  • 1
math4tots
  • 8,540
  • 14
  • 58
  • 95
  • 3
    Frankly I like the original/normal/standard way. I see it dozens of times everyday. I know exactly how it works and what it does. This is a place IMO where an extra abstraction will detract greatly from the readability of your code. Now I have to go dig up your macro thingy that may jump through python magic to do amazing things. – Doug T. Nov 19 '12 at 22:28

3 Answers3

2

you could make Foo and all others as subclasses of a master Class, ie,

class MasterObject(object):
  def __init__(self,a,b,c):
    self.a = a
    self.b = b
    self.c = c


class Foo(MasterObject):
  def __init__(self,a,b,c):
    MasterObject.__init__(a,b,c)
Cameron Sparr
  • 3,925
  • 2
  • 22
  • 31
2

It's weird, but you could use __slots__ to achieve this:

class Base(object):
    def __init__(self, *args, **kw):
        for k,v in zip(self.__slots__, args):
            setattr(self, k, v)

        for k,v in kw.items():
            setattr(self, k, v)

class ChildA(Base):
    __slots__ = 'a', 'b', 'c'

class ChildB(Base):
    __slots__ = 'x', 'y', 'z'

You could also use the following technique to save yourself some typing when initializing classes with lots of arguments:

def autoargs(l):
    self = l.pop('self')
    for k,v in l.items():
        setattr(self, k, v)

class Base(object):
    def __init__(self, a, b, c):
        autoargs(locals())

I hope I'm understanding your question correctly.

gvalkov
  • 3,977
  • 30
  • 31
  • Flashback: the `autoargs` snippet is from [O'Reilly's Python Cookbook, Second Edition](http://shop.oreilly.com/product/9780596007973.do) - great book that's still surprisingly relevant, given that it covers Python 2.3 and 2.4. – gvalkov Nov 19 '12 at 22:51
0

you can do something like this

class Foo(object):
    def __init__(self, **kw):
        self.__dict__.update(kw)
        del self.__dict__["self"]

but then you have to name all the instance variables every time you instantiate the class. I think this makes the code more fragile. Since most people don't like fragile code, they stick with the explicit version.

You could write a macro for your editor to expand them I suppose, but I don't think a very large percentage of time is spent on that detail, and not all classes want to save all the arguments into the instance.

John La Rooy
  • 295,403
  • 53
  • 369
  • 502