Home > Back-end >  What is the proper way to define a class when a function is an optional parameter?
What is the proper way to define a class when a function is an optional parameter?

Time:12-18

I have declared a class that accepts a function as optional parameter. When this function parameter is not set, a default class method is used. Otherwise, I use my own function. My code has the following structure :

class myClass:
    def __init__(self,msg,foo=None):
        self.msg=msg
        self.foo=foo
        
    def print(self):
        if (self.foo == None):
            self.innerPrint()
        else :
            self.foo(self.msg)
        
    def innerPrint(self):
        print("Inner Print : ",self.msg)
        
def outerPrint(msg):
    print("Outer Print : ",msg)

So,

myObj1=myClass("Hello")
myObj1.print()

prints : Inner Print : Hello

and

myObj2=myClass("Hello",outerPrint)
myObj2.print()

prints : Outer Print : Hello

Is it the proper way to do that or is it possible to simplify this code ?

Someone has posted an answer that has been removed (It is unfortunate because it helps me).

So this is my new code structure :

class myClass:
    def __init__(self,msg,foo=None):
        self.msg=msg
        self.printFoo=(foo or self._innerPrint)
        
    def print(self):
        self.printFoo(self.msg)
        
    def _innerPrint(self,msg):
        print("Inner Print : ",msg)
        
def outerPrint(msg):
    print("Outer Print : ",msg)

My class method : print has only one line now. Is it a good practise ?

CodePudding user response:

Your second solution is better, because there is no need to check self.foo for every call to your print method, It is assigned once in the __init__ method.

You can also use "properties" for this : (I changed some of your variable names to follow naming conventions)

from functools import partial

class MyClass:
    def __init__(self, msg, foo=None):
        self.msg = msg
        self.myprint = foo

    @property
    def myprint(self):
        return self._func

    @myprint.setter
    def myprint(self, fn):
        self._func = partial(fn, self.msg) if fn else self.inner_print

    def inner_print(self):
        print("Inner Print : ", self.msg)


def outer_print(msg):
    print("Outer Print : ", msg)


my_obj1 = MyClass("Hello")
my_obj1.myprint()
print("-----------------------------------")
my_obj1 = MyClass("Hello", outer_print)
my_obj1.myprint()

output:

Inner Print :  Hello
-----------------------------------
Outer Print :  Hello

Once you create an instance of your class, The setter is get called in self.myprint = foo line. When your myprint returns self._func, it is either your inner_print function, or the partial function that is created with passed foo function.

* I used partial class because I had to. Your outer_print function need a parameter.

  • Related