On 02/26/2018 03:41 PM, Steven D'Aprano wrote:
I have a class with a large number of parameters (about ten) assigned in
`__init__`. The class then has a number of methods which accept
*optional* arguments with the same names as the constructor/initialiser
parameters. If those arguments are None, the defaults are taken from the
instance attributes.

An example might be something like this:


class Foo:
     def __init__(self, bashful, doc, dopey, grumpy,
                        happy, sleepy, sneezy):
         self.bashful = bashful  # etc

     def spam(self, bashful=None, doc=None, dopey=None,
                    grumpy=None, happy=None, sleepy=None,
                    sneezy=None):
         if bashful is None:
             bashful = self.bashful
         if doc is None:
             doc = self.doc
         if dopey is None:
             dopey = self.dopey
         if grumpy is None:
             grumpy = self.grumpy
         if happy is None:
             happy = self.happy
         if sleepy is None:
             sleepy = self.sleepy
         if sneezy is None:
             sneezy = self.sneezy
         # now do the real work...

     def eggs(self, bashful=None, # etc...
                    ):
         if bashful is None:
             bashful = self.bashful
         # and so on
There's a lot of tedious boilerplate repetition in this, and to add
insult to injury the class is still under active development with an
unstable API, so every time I change one of the parameters, or add a new
one, I have to change it in over a dozen places.

Is there a good fix for this to reduce the amount of boilerplate?


Thanks,




def snatchit(func):
    def snatched(self, *args, **kwargs):
        frame = inspect.signature(func)
        for name in frame.parameters:
            if name != 'self':
                kwargs.setdefault(name, getattr(self, name))
        return func(self, *args, **kwargs)
    snatched.__name__ = func.__name__
    snatched.__doc__ = func.__doc__
    return snatched


class Foo(object):
    def __init__(self, sleepy, groggy):
        self.sleepy = sleepy
        self.groggy = groggy

    @snatchit
    def spam(self, sleepy=None):
        print("I am spam. sleepy=", sleepy)

    @snatchit
    def ham(self, sleepy=None, groggy=None):
        print("I am ham. sleepy=", sleepy, " and groggy=", groggy)


>>> f = Foo(1, 19)
>>> f.spam()
I am spam. sleepy= 1
>>> f.spam(sleepy=8)
I am spam. sleepy= 8
>>> f.ham(sleepy=8)
I am ham. sleepy= 8  and groggy= 19
>>> f.ham(sleepy=17, groggy=888)
I am ham. sleepy= 17  and groggy= 888

--
~ Jugurtha Hadjar,

--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to