5

Frequently the constructor of a class will take it's arguments and save them on the instance. For example:

class Example(object):
    def __init__(self, title='',backtitle='', height=20, width=50):
        self.title = title
        self.backtitle = backtitle
        self.height = height
        self.width = width

This is repetitious so I made a helper function to do this automatically:

from inspect import getargspec
def save_args(values):
    for i in getargspec(values['self'].__init__).args[1:]:
        values['self'].__dict__[i] = values[i]

class Example(object):
    def __init__(self, title='',backtitle='', height=20, width=50):
        save_args(vars())

My questions are as follows:

  • Will this fail with certain classes or agruments
  • Is it portable, will it work on Jython, etc.. It worked for me on python 2.7 and 3.2
  • Is there a simpler alternative?
  • Is there a python package out there that already does this?

2 Answers 2

6

It'll fail when your class uses __slots__. You could use setattr() instead:

from inspect import getargspec
def save_args(values):
    for i in getargspec(values['self'].__init__).args[1:]:
        setattr(values['self'], i, values[i])

provided the arguments keyword arguments to __init__ are all declared slots of course.

Otherwise this should work on any Python implementation.

You may be interested in a previous discussion of the topic, which sparked a Python-ideas list thread.

Sign up to request clarification or add additional context in comments.

7 Comments

FGITW -- That's what I get for trying to address each of OP's questions individually when really only the first one was important :)
There was a discussion about this on python-ideas somewhere in the past 6 months, where (after everyone decided nothing had to be added to the language) people proposed and argued about 300 different implementations. It's worth searching the archives if you really care about this. (IIRC, if you don't care about portability, there's a solution using frame hackery that's handles some cases that getargspec can't… but I don't remember what cases.)
This might also be neatly handled in a meta-class which wraps the existing __init__, although I haven't really fully formed how that would work in my head (mostly because I'm pretty inexperienced with metaclasses)
@mgilson: a decorator on a __init__ method with just a pass body would do too.
Yeah, that's true too. I do have some experience with decorators :)
|
1

This requires you to write more code, silently ignores all erroneous arguments to the Example constructor, and doesn't support positional arguments to the Example constructor, but avoids use of inspect:

def save_args(obj, defaults, kwargs):
    for k,v in defaults.iteritems():
        if k in kwargs: v = kwargs[k]
        setattr(obj, k, v)

class Example(object):
    def __init__(self, **kwargs):
        defaults = { 'title': '',
                     'backtitle': '',
                     'height': 20,
                     'width': 50 }
        save_args(self, defaults, kwargs)

2 Comments

What's wrong with inspect? As long as the ugly is sufficiently hidden, I don't see any problem with it :)
Nothing's wrong with inspect, I just wanted to demonstrate that it could be done without.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.