1

I am creating a very simple Calculator class and I want to create a subtraction method that works self sufficiently, or at least within the methods specified by the class itself.

The problem is that, for subtraction if I use the -= similarly to how I use the += for the addition, it will not work properly and give me the first number already subtracted to the starting value of 0.

The method takes in *args, so I can give as many numbers as I want, and I am now trying to make it so that it takes the first argument/number as default value and then subtracts the sum (using my own addition method) of the other numbers to this number.

This is the code I came up with until now:

class Calculator:
    """An attempt to create a calculator."""

    def __init__(self):
        self.current_value = 0

    # type hinting stuff:
    # https://stackoverflow.com/questions/50928592/mypy-type-hint-unionfloat-int-is-there-a-number-type
    def add(self, *args: float, reset=False):
        """
        Takes in a series of numbers as iterable and sums them up.

        If the iterable is empty, or has only one value, the function is invalid.

        :param args: Creates an iterable of any number. Can be `int` or `float`.
        :param reset: A boolean flag. If set to True, resets the current value to 0.
        :return: Return the sum of the 'start' value (default: 0) plus an iterable of numbers.
        """

        if reset:
            self.current_value = 0

        if len(args) >= 1:
            total = self.current_value
            for num in args:
                if isinstance(num, (int, float)):
                    total += num
                else:
                    print(f"Insert only valid numbers (integers or floats).  Try again...")

            self.current_value = total
            return total

        else:
            print(f"Insert at least one valid number (integer or float). Try again...")

    def subtract(self, *args: float, reset=True):
        """
        Takes in a series of numbers as iterable and subtracts them to the starting value of the first number.

        If the iterable is empty, the function returns 0.

        :param args: Creates an iterable of any number. Can be `int` or `float`.
        :param reset: A boolean flag. If set to True, resets the current value to 0.
        :return: Return the subtraction of the values inputted as iterables.
        """

        if reset:
            self.current_value = 0

        if len(args) >= 1:

            for num in args:
                if isinstance(num, (int, float)):
                    arg += num
                    continue
                else:
                    print(f"Insert only valid numbers (floats or integers). Try again...")
                    return None


            print(f'Current value: {self.current_value}')
            print(f'Sum of args', self.add(args))

            total = self.current_value - self.add(args)


            self.current_value = total
            return total

        else:
            print(f"Insert at least one valid number (integer or float). Try again...")

The current value is used to retain memory of the previous operations. So, for example if I do add(5,2) = 7 and then call subtract(3) it will be = 4 because the calculator has 7 stored in its memory until I reset it manually.

spool
  • 25
  • 5

1 Answers1

2

Subtracting numbers is the same as adding the negative of each number. So you could simplify subtract() to:

def subtract(self, *args: float, reset=True):
    return self.add(*(-arg for arg in args), reset=reset)
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • I was going to recommend the same once the OP had realized that `add()` and `subtract()` potentially only differed by `-=`. – JonSG Jun 02 '23 at 18:37
  • Thank you for the all the tips throughout the post. I have a question: if I were to use this with a call for ex. calculator.subtract(4) and assuming I have reset the memory, wouldn't this still give me the wrong output of -4? I wanted to make it so that, if there is nothing in the memory (aka current_value = 0), a user cannot subtract a number from nothing. – spool Jun 02 '23 at 20:02
  • Why do you want that? This isn't a bank account, it's a calculator, so negative numbers should be fine. – Barmar Jun 02 '23 at 20:11
  • Hmm, I wanted to make my method much like sum(), where if you only give 1 input number it will say it's not an iterable. I guess it does make sense though, as sum() doesn't have this memory concept built in. – spool Jun 02 '23 at 20:23
  • 1
    If you want it to be like `sum()` you shouldn't use `*args`. Use `args` to take one iterable argument. – Barmar Jun 02 '23 at 20:25