Can't figure out how to create a "list" instance variable using class in Python

This is my code:

class Category():

    
    def __init__(self,category,balance=0,ledger=[]):
        self.category = category
        self.balance = balance
        self.ledger = ledger

    def check_funds(self,amt):
        if amt > self.balance:
            return False
        else:
            return True
    

    def deposit(self, dep_amt, description=""):
        self.balance +=dep_amt
        dep_note = "{\"amount\": "+str(dep_amt)+", \"description\": "+description+"}"
        self.ledger.append(dep_note)
        
    def withdraw(self, wd_amt, description=""):
        if not self.check_funds(wd_amt):
            return False
        else:
            self.balance -= wd_amt
            wd_note = "{\"amount\": "+"-"+str(wd_amt)+", \"description\": "+description+"}"
            self.ledger.append(wd_note)
            return True
        
    def get_balance(self):
        return self.balance
    
    def transfer(self,tf_amt,category):
        wd_description = "Transfer to "+category.category
        dp_description = "Transfer from "+self.category
        self.withdraw(tf_amt,wd_description)
        category.deposit(tf_amt,dp_description)
    
    

Creating instances:

food = Category('food')
food.deposit(1000,"food initial deposit")
food.withdraw(300,"groceries")

clothing = Category('clothing')
clothing.deposit(1000,"clothes initial deposit")
clothing.withdraw(20,"pants")
food.transfer(200,clothing)
    

While running the code clothing.ledger this is the output:

['{"amount": 1000, "description": food initial deposit}', '{"amount": -300, "description": groceries}', '{"amount": 1000, "description": clothes initial deposit}', '{"amount": -20, "description": pants}', '{"amount": -200, "description": Transfer to clothing}', '{"amount": 200, "description": Transfer from food}']

This is what I'm looking for:

['{"amount": 1000, "description": clothes initial deposit}', '{"amount": -20, "description": pants}', '{"amount": -200, "description": Transfer to clothing}']

basically my ledger attribute take all the instances which is what I don't want.

Upvotes: 0

Views: 305

Answers (1)

mr_mooo_cow
mr_mooo_cow

Reputation: 1128

When passing dynamic or mutable(list, dictionary) default values in Python it is best practice to set them as None and to specify their intended value(s) inside the function.

def __init__(self,category,balance=0,ledger=None):
    If ledger is None:
        ledger = []
    self.category = category
    self.balance = balance
    self.ledger = ledger

Otherwise ledger is only evaluated a single time. Reference: https://medium.com/python-features/how-to-avoid-classic-pitfall-while-passing-default-values-in-python-7002c0dc4c7c

Upvotes: 1

Related Questions