2

I'm new to programming with python and I'm working on the python 4 everybody course. For that I need to build a budget app. In specific, this is the first two tasks:

Complete the Category class in budget.py. It should be able to instantiate objects based on different budget categories like food, clothing, and entertainment. When objects are created, they are passed in the name of the category. The class should have an instance variable called ledger that is a list. The class should also contain the following methods:

A deposit method that accepts an amount and description. If no description is given, it should default to an empty string. The method should append an object to the ledger list in the form of {"amount": amount, "description": description}.

A withdraw method that is similar to the deposit method, but the amount passed in should be stored in the ledger as a negative number. If there are not enough funds, nothing should be added to the ledger. This method should return True if the withdrawal took place, and False otherwise.

My attempt for now is the following:

class Category:
    def __init__(self):
        self.ledger = []
        Total = 0

    def deposit(self, amount, *description):
        self.ledger.append({"amount": amount, "description": description})
              
        return self.ledger

    def withdraw(self, withdrawal):
        
        for x in self.ledger:
            if x == int():
                return sum
            
        self.ledger.append({"withdrawal": withdrawal})
        
        return self.ledger

I think I have multiple questions:

  1. What is a list with {} as one Item? Is it a 5.4. "Set"?
  2. How can I now implement the requirement of the withdraw method "If there are not enough funds, nothing should be added to the ledger." I think I need to sum up all the integers of the list self.ledger, but idk how to grab those from it and sum it up. I tried as you can see a for loop, but I think that is incorrect syntax?

I really appreciate every help and am grateful for also some background knowledge!

Thanks in advance! Lukas

lukaslohm
  • 23
  • 3
  • 1
    `{}` is an empty dict. We don't have a similar notation for an empty set: https://stackoverflow.com/questions/6130374/empty-set-literal – VPfB Sep 06 '21 at 12:47
  • 1
    {} is an empty dictionary. set() is an empty set. However, {1,2} is a set whereas {1:2} is a dictionary –  Sep 06 '21 at 12:49

2 Answers2

0
  1. {} is en empty dict. An empty set is set()

  2. This should do for the withdraw function :

     def withdraw(self, amount, description):
    
         balance = sum(transaction["amount"] for transaction in self.ledger)
    
         if balance >= withdrawal :
             self.ledger.append({"amount": -amount, "description": description})
             return True
         else :
             return False
    
     return self.ledger
    

This use a generator as an argument for the builtin sum function. This may be a bit advanced if you are just starting python so you can also compute the balance with more beginner friendly code :

    balance = 0
    for transaction in ledger:
        balance = balance + transaction["amount"]
        # you can shorten the line above to
        # balance += transaction["amount"]

This is roughly equivalent to what the sum and the generator syntax do.

Out of curiosity, is the * in front of description argument in your deposit function a typo ?

Niko B
  • 751
  • 5
  • 9
  • Thank you for your answer! It really helped me out here! So the * is for indicating that it is an optional argument in my method. At least I thought so. :D – lukaslohm Sep 07 '21 at 10:38
-1

So, some things for clarification.

  1. self.ledger = []: The [] makes the ledger a list, and the self. part makes it an instance variable, only applicable to a specific instance of the class Category
  2. As stated in the comments, {"key": "value"} is a dict object. Using self.ledger.append({"key": "value"}) adds the dict object {"key": "value"} to the ledger list.
  3. Normally if you want to keep track of a number inside a class, you create an instance variable and update it when it gets changed. See the usage of self.total below.
  4. Recalculating the total can also be done, see the method update_total() below.

I added some testing below.

class Category:
    def __init__(self):
        self.ledger = []
        # total also needs the "self." to make it an instance variable, just
        # as the ledger above
        # if you omit the "self."" it's a localized variable only available
        # to the __init__ method itself.
        self.total = 0

    def deposit(self, amount, *description):
        self.ledger.append({"amount": amount, "description": description})
        # add the amount to the total
        self.total += amount
        return self.ledger

    def withdraw(self, withdrawal):
        # make the withdrawal negative
        if abs(withdrawal) == withdrawal:
            withdrawal = 0 - withdrawal
        # check if there's enough in the total
        if abs(withdrawal) <= self.total:
            # update the total
            self.total += withdrawal
            # add to the ledger
            self.ledger.append({"withdrawal": withdrawal})
        else:
            # you could return an error message here
            pass
        return self.ledger

    def update_total(self):
        total = 0
        for item in self.ledger:
            # need to check if the amount key is in the dict object
            if "amount" in item:
                total += item["amount"]
            # this check below is not needed but it ensures future compatability
            elif "withdrawal" in item:
                total += item["withdrawal"]
        # just because, you can check if the totals match
        if self.total != total:
            print(
                f"""Difference in totals found. Someone is cheating :-|
  Instance total:   {self.total}
  Calculated total: {total}"""
            )
        # set the instance variable to the local variable
        self.total = total
        return self.total



from pprint import pprint
nr1 = Category()
nr2 = Category()

for i in range(10):
    nr1.deposit(i, f"deposit - {i}")

pprint(nr1.ledger)
print(f"Total: {nr1.total}")
nr1.withdraw(10)
print(f"Total: {nr1.total}")
nr1.withdraw(-10)
print(f"Total: {nr1.total}")
nr1.withdraw(99999)
print(f"Total: {nr1.total}")
pprint(nr1.ledger)
print(nr1.update_total())
nr1.total = 123
print(nr1.update_total())

# just to show that the above only updated the values inside the nr1 instance.
print(f"Total for nr2: {nr2.total}")
Edo Akse
  • 4,051
  • 2
  • 10
  • 21