Rookie1999
Rookie1999

Reputation: 151

How to define *args in a constructor function of a Class

I've started self learning Python and need some advise on the below problem which I'm working on currently.

  1. How should I use the constructor method without knowing the total number of arguments to be passed.

How should I decorate each method of the calculator class, with a custom method that logs the arguements.(using a custom logger method)

Something like below:

The Input Values are : '10' '21' and '15' # if *args were 10, 21 & 15

Operation : Multiply

My unfinished code.

import logging


class Calculator:

    def add(self, *args):
        total = 0
        for val in args:
            total += int(val)
        return total

    def subtract(self, *args):
        total = 0
        for val in args:
            total -= val
        return total

    def multiply(self, *args):
        total = 1
        for val in args:
            total *= val
        return total

    def divide(self, *args):
        total = 1
        for val in args:
            total /= val
        return total

Below operations gives incorrect values:

print(Calculator.multiply(10, 2, 4))
print(Calculator.subtract(10, 2, 4))
print(Calculator.add(10,2,4))
print(Calculator.divide(10,2,4))

8
-6
6
0.125

Upvotes: 1

Views: 225

Answers (1)

gelonida
gelonida

Reputation: 5630

There's two problems.

The first problem is, that you create a class so you you have to instantiate an object before using it:

calculator = Calculator()
print(calculator.multiply(10, 2, 4))
print(calculator.subtract(10, 2, 4))
print(calculator.add(10,2,4))
print(calculator.divide(10,2,4))

if you type Calculator.add(10,2,4)) then the 10 will be passed as self and only 2 and 4 will be passed as args, so args would have been [2, 4] instead of your expected [10, 2, 4]

The second problem is, that for substract and divide you have to treat the first parameter differently.

So following should work:

import logging

logger = logging.getLogger(__name__)

class Calculator:

    def add(self, *args):
        logger.info("calc add %s", args)
        print("calc add ", args)
        total = 0
        for val in args:
            total += int(val)
        return total

    def subtract(self, *args):
        logger.info("calc subtract %s", args)
        print("calc substract ", args)
        if len(args) == 0:
            return 0
        total = args[0]
        for val in args[1:]:
            total -= val
        return total

    def multiply(self, *args):
        logger.info("calc multiply %s", args)
        print("calc multiply ", args)
        total = 1
        for val in args:
            total *= val
        return total

    def divide(self, *args):
        logger.info("calc divide %s", args)
        print("calc divide ", args)
        if len(args) == 0:
            return 1
        total = args[0]
        for val in args[1:]:
            total /= val
        return total


# Let's assume, that's the main function
logging.basicConfig(filename='example.log',level=logging.DEBUG)

calculator = Calculator()
print(calculator.multiply(10, 2, 4))
print(calculator.subtract(10, 2, 4))
print(calculator.add(10,2,4))
print(calculator.divide(10,2,4))

I added print statements for debugging. You had to remove them of course for 'production'

I configured the logging to write all logs with level DEBUG, INFO, WARNING, ERROR and critical for all modules into a log file.

To setup logging as you wish can be rather complex depending on your use case.

https://docs.python.org/3.8/library/logging.html is very complex and gives you a lot if freedom. This is perhaps better treated in a separate question

Addendum:

Concerning the __init__ function as you asked in one comment.

you might want to have a calculator, that remembers the last calculated

IN this case you would change your code slightly.

You would add an __init__() method

    def __init__(self):
        last_result = 0  # just some value

Then you had to change multiply, subtract, ... to store the last caclulated result.

e.g.

    def add(self, *args):
        logger.info("calc add %s", args)
        print("calc add ", args)
        total = 0
        for val in args:
            total += int(val)
        self.last_result = total  # no you remember the last result.
        return total

And if you wanted you could check now the last result. with print(calculator.last_result)

What might really make sense for a calculator?

Perhaps the last n calculations (operation + parameters + result).

Perhaps a memory and a command to add or subtract the last result to that memory.

Upvotes: 2

Related Questions