1

Suppose a class myClass has two method definitions _call1 and _call2, but only one of them should be used depending on a parameter passed when the object is instantiated, and a specific alias call is given for the chosen method. How to program this? A minimum example is shown below.

The reason behind this code is that I would like to avoid the overhead of having an if-else statement with two possible returns inside a single call method. Another option would be to create two different possible classes based on cond_param, but I'd rather avoid that.

class myClass:
    def __init__(self, cond_param):
        self.cond_param = cond_param
        # depending on the value of the conditional parameter `cond_param`,
        # a method named `call` will be assigned to one of the methods
        # defined below
        if self.cond_param not in [1, 2]:
            return ValueError
        if self.cond_param == 1:
            call = _call1
        else
            call = _call2

    def _call1(self):
        return "call 1!"

    def _call2(self):
        return "call 2!"

obj1 = myClass(1)
print(obj1.call()) # should print "call 1!"

obj2 = myClass(2)
print(obj2.call()) # should print "call 2!"
Breno
  • 748
  • 8
  • 18
  • Use a dictionary? `calls = {1: _call1, 2: _call2}` => `call = calls[cond_param]`. – Vepir Jun 12 '21 at 18:52
  • If so, this is duplicate of [Avoid if else to instantiate a class - python](https://stackoverflow.com/q/51627294/5821790)? – Vepir Jun 12 '21 at 18:59
  • Is the dictionary an attribute of the class? And can `call` be defined inside `__init__`? The example given in the question is not a working example. It fails because inside `__init__`, `_call1` and `_call2` are undefined. – Breno Jun 12 '21 at 19:08

1 Answers1

2

You can avoid if-else with a dictionary.

You need to use self. to be able to reference something everywhere in the class. Also, you should use raise to raise an error, not return which would return the error class itself.

Fixing your code

class myClass:
    def __init__(self, cond_param):
        self.cond_param = cond_param
        # depending on the value of the conditional parameter `cond_param`,
        # a method named `call` will be assigned to one of the methods
        # defined below
        self._calls = {1: self._call1, 2: self._call2} 
        self.call = self._calls.get(cond_param, self._callErr)

    def _call1(self):
        return "call 1!"

    def _call2(self):
        return "call 2!"
    
    def _callErr(self):
        raise  ValueError

obj1 = myClass(1)
print(obj1.call()) # should print "call 1!"

obj2 = myClass(2)
print(obj2.call()) # should print "call 2!"

obj3 = myClass(3)
print(obj3.call()) # should raise ValueError

gives

call 1!
call 2!
Traceback (most recent call last):

    ...

ValueError

as expected.

Vepir
  • 612
  • 1
  • 8
  • 21