Python Forum

Full Version: How to pass a method as argument in an another method?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I want to write a python calculator program that has different methods to add, subtract, multiply which takes 2 parameters. I need to have an execute method when passed with 3 parameters, should call respective method and perform the operation. How can I achieve that?

class calc():
    def __init__(self,a,b):
        self.a=a
        self.b=b
        
    def ex(self,fun):
        self.fun=fun
        if fun=="add":
            self.add()
    
    def add(self):
        return self.a+self.b
    def sub(self):
        return self.a-self.b
    def mul(self):
        return self.a*self.b
    def div (self):
        return self.a/self.b
    def execu(
obj1=calc()
obj1.ex("add",1,,2)
Why do you want to put that logic in your class, instead of having it be outside? You can of course pass functions to other functions, but it doesn't really make sense here.
The execute method needs to have the 2 number parameters and needs to update the instance attributes.
class Calculator:
    def __init__(self):
        self.number1 = 0
        self.number2 = 0
        self.result = 0
        self.operator = ""

    def execute(self, func, number1, number2):
        self.number1 = number1
        self.number2 = number2
        if func == "add":
            self.add()

    def add(self):
        self.result = self.number1 + self.number2
        self.operator = "+"

    def sub(self):
        self.result = self.number1 - self.number2
        self.operator = "-"

    def mul(self):
        self.result = self.number1 * self.number2
        self.operator = "*"

    def div(self):
        self.result = self.number1 / self.number2
        self.operator = "/"

    def __str__(self):
        return f"Result: {self.number1} {self.operator} {self.number2} = {self.result}"


calculator = Calculator()
calculator.execute("add", 1, 2)
print(calculator)

Rather than having a chain of if statements you can use a dictionary instead
class Calculator:
    def __init__(self):
        self.number1 = 0
        self.number2 = 0
        self.result = 0
        self.operator = ""
        self.commands = {
            "add": self.add,
            "sub": self.sub,
            "mul": self.mul,
            "div": self.div,
        }

    def execute(self, func, number1, number2):
        self.number1 = number1
        self.number2 = number2
        command = self.commands[func]
        command()

    def add(self):
        self.result = self.number1 + self.number2
        self.operator = "+"

    def sub(self):
        self.result = self.number1 - self.number2
        self.operator = "-"

    def mul(self):
        self.result = self.number1 * self.number2
        self.operator = "*"

    def div(self):
        self.result = self.number1 / self.number2
        self.operator = "/"

    def __str__(self):
        return f"Result: {self.number1} {self.operator} {self.number2} = {self.result}"


calculator = Calculator()
calculator.execute("add", 1, 2)
print(calculator)
Hey thanks for the response. I guess we don't need an init function here. Checkout the trimmed the code.
#calculator class with arithmetic methods

class calc:
 
    def execute(self, func, a, b):
        self.a = a
        self.b = b
        if func == "add":
            self.add()
        elif func == "sub":
            self.sub()
        elif func == "mul":
            self.mul()
        elif func == "div":
            self.div()
 
    def add(self):
        print (self.a,"+",self.b,"=",self.a + self.b)
      
 
    def sub(self):
          print (self.a,"-",self.b,"=",self.a - self.b)
     
 
    def mul(self):
          print (self.a,"*",self.b,"=",self.a* self.b)
        
 
    def div(self):
        print (self.a,"/",self.b,"=",self.a / self.b)
       
 
 
cal = calc()
cal.execute("div", 6, 3)
You successfully turned the class into what may as well be separate functions.
It's homework. Don't expect it to make any sense. A real program would not write methods for code already provided in the operator library. A real program would not use strings like 'add' or 'sub' instead of '+' or '-'. A real program would not write a class when a simple function would suffice.

It is a wonder that anyone ever learns what "object oriented" means when you see so few examples where the "object oriented" benefits are demonstrated.
If you define the math functions you may as well make them generally useful. I would do something like this:
#calculator class with arithmetic methods

class calc():
    def solve(self, equation):
        '''Solve eqation in the form a op b where b is in "+-*/"'''
        a, op, b = equation.split()
        print(equation, '=', self.execute(op, float(a), float(b)))

    def execute(self, op, a, b):
        '''Return result of binary math operation'''
        if op == "+":
            return self.add(a, b)
        if op == "-":
            return self.sub(a, b)
        if op == "*":
            return self.mul(a, b)
        if op == "/":
            return self.div(a, b)
        raise ValueError(f'{op} is not a recognized operator')

    def add(self, a, b):
        '''Return a + b'''
        return a + b

    def sub(self, a, b):
        '''Return a - b'''
        return a - b

    def mul(self, a, b):
        '''Return a * b'''
        return a * b

    def div(self, a, b):
        '''Return a / b'''
        return a / b

cal = calc()
cal.solve('6 / 3')
print(cal.execute('*', 2, 3))
If we pretend that the calculator has support for more interesting operations, making those operations visible outside the calculator changes it from an application to a library. Your code exposed the operations, but not in a generically useful way. If I am using your library I probably want the div function to return the quotient instead of None.

Though this is a silly program it aspires to do "good design" things like separating the implementation from the interface. add(a, b) knows how to compute a + b. It should not have to know about how results are displayed (there should not be a print). execute(op, a, b) does not know how to do any operations, but it knows how to find the right function for the operator. solve(equation) does not know anything about math, but it knows how to parse an equation and display the results. When you design code you should look for this kind of division of labor. Every function should do one thing that is easily described with a sentence or two. If you cannot describe what a function does you need to "refactor" your code to have functions that are well defined.