3

I currently implementing a class called BankAccount. It offers the ability to set a balance, make a deposit, make a withdrawal, and check the balance.

Now I have to write a function (called processAccounts()) that will take the name of a file as its parameter. The first line of the file will be a number which specified the initial bank account balance. The lines that follow will specify a series of withdrawals and deposits marked by w or W for withdrawals and d or D for deposits. The function must read the the text file, set the initial balance, and then make withdrawals or deposits based on the contents of the text file.

Here is what I have so far:

class BankAccount:

    def set(self,balance=0):
        self.balance=balance        
    def deposit(self,amount):
        self.balance += amount
    def withdraw(self,amount):
        self.balance -= amount
    def get_balance(self):
        return self.balance
def processAccounts(fname):
    with open(fname,'r') as f:
    acct=[]
    for line in f:
        line=line.split()
        if line:
            line= [int(i) for i in line]
            acct.set(line)

Text File:

1000.00
W 50.50
W 5.25
d 100.75
w 525.15
d 85.70

I am currently trying to set up the first part which will read the first line and then call upon the set() function to set the initial balance.

The error I'm getting is:

ValueError: invalid literal for int() with base 10: '1000.00'

Am I approaching this problem incorrectly or did I just not do it correctly?

DavidRR
  • 18,291
  • 25
  • 109
  • 191
iggyami
  • 43
  • 1
  • 6

3 Answers3

8

The general approach is correct, but int is clearly wrong since apparently the amounts are expressed in "dollars.cents".

float would appear to work but would probably not be the right choice: handling monetary amounts is instead the primary reason the decimal module was added to the Python standard library! With decimal you'll get precise computations, without the risk of rounding errors losing or gaining a cent here and there which would unchain The Auditors upon you.

So here's how I'd do it...:

import decimal

class BankAccount:

    def set(self,balance=decimal.Decimal('0.00'):
        self.balance = balance  

# the rest of the class is fine.  Shd probably have an __init__ tho.
# also should keep an audit trail of deposit and withdrawals!

def processAccounts(fname):
    with open(fname,'r') as f:
        start_bal = decimal.Decimal(next(f).strip())
        ba = BankAccount()
        ba.set(start_bal)
        for line in f:
            fields = line.strip().split()
            if fields:
                if fields[0] in 'Ww':
                    ba.withdraw(decimal.Decimal(fields[1])
                elif fields[0] in 'Dd':
                    ba.deposit(decimal.Decimal(fields[1])
                else:
                    print('Ignoring line: {!r}'.format(line.strip()))
    return ba
Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
0

First, since you are working with money the correct answer is to use the decimal class as suggested by Alex Martelli.

Having said that, the answer to the specific problem of the ValueError can be solved with a 3rd party module called fastnumbers (I am the author). It provides a function called fast_forceint that will corerce strings of floats to (i.e. '1000.00') to an int.

>>> from fastnumbers import fast_forceint
>>> fast_forceint('1000.00')
1000
>>> isinstance(fast_forceint('1000.00'), int)
True

This library was specifically designed to ease the pain of converting strings to numeric types.

SethMMorton
  • 45,752
  • 12
  • 65
  • 86
0

To do so without using the decimal class (less accurate when working with floats), also including a constructor:

class BankAccount():

def __init__(self, initialBalance = 0):
    self.accBalance = initialBalance 

def __repr__(self):
    return("BankAccount({})".format(self.accBalance))

def set(self, amount):
    self.accBalance = amount

def deposit(self, amount):
    self.accBalance += amount

def withdraw(self, amount):
    self.accBalance -= amount

def balance(self):
    return(self.accBalance)


def processAccount(filename ):
    with open(filename,'r') as f:
        b = BankAccount()
        startBal = f.readline().split()
        startBal = float(startBal[0])
        b.set(startBal)

        for line in f:
            fields = line.strip().split()
            if fields[0] in 'Ww':
            b.withdraw(float(fields[1]))
            elif fields[0] in 'Dd':
                b.deposit(float(fields[1]))

    return b
Frank
  • 339
  • 8
  • 18