b-fg
b-fg

Reputation: 4137

Aliase a class function to be assigned from init method

Given I have a class such as:

class Model(object):
    def __init__(self, foo = 'bar'):
        if foo == 'bar':
            self.f = self._sse
        else:
            self.f = None

    def _sse():
        pass

Is there a way I can create an alias so I do not have to check what's the value of the non-positional argument foo? Something like

class Model(object):
    alias = {'bar': _sse}
    def __init__(self, foo = 'bar'):
        self.f = foo

    def _sse():
        pass

Upvotes: 0

Views: 179

Answers (2)

b-fg
b-fg

Reputation: 4137

Using @KlausD. suggestion and including alias in the __init__ method does the trick for me.

class Model(object):
    def __init__(self, foo = 'bar'):
        alias = {'bar': self._sse,
                 'bar2': self._sse2}

        self.f = alias.get(foo)

    def _sse(self):
        print('in sse')
    def _sse2(self):
        print('in sse2')


m = Model(foo='bar')
m.f() # in sse
m = Model(foo='bar2')
m.f() # in sse2

Upvotes: 0

bruno desthuilliers
bruno desthuilliers

Reputation: 77912

Technical answer: you can do it by defining the target function before the initializer, referencing this function as the default argument (Python functions are objects too), and manually invoking the descriptor protocol on the target function:

>>> class Model(object):
...     def _sse(self):
...         print("in self._sse")
...     def __init__(self, foo=_sse):
...         self.f = foo.__get__(self, type(self))
... 
>>> m = Model()
>>> m.f()
in self._sse

Just note that with this solution, if you want to pass another function, this function has to take self as first argument :

>>> # doesn't work
... def bar(): print("bar")
... 
>>> m2 = Model(bar)
>>> m2.f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() takes no arguments (1 given)
>>> # works:
... def baaz(self): print("baaz({})".format(self))
... 
>>> m3 = Model(baaz)
>>> m3.f()
baaz(<__main__.Model object at 0x7fc3e2337090>)

Now from a readability POV this is barely an improvement IMHO...

EDIT: as Aran-Fey mentions, this doesn't exactly answer the question so for a more "literal" version (and that doesn't require special definitions ordering etc):

class Model(object):
    def _sse(self):
        print("in self._sse")

    alias = {"bar": "_sse"}

    def __init__(self, foo="bar"):
        self.f = getattr(self, self.alias.get(foo, "___"), None)

But this is still not improving readability...

Upvotes: 1

Related Questions