0

Teaching myself python at the moment and I am trying to make a simple payment script, I've hit a bit of a block here, I have tried to use a function to construct a simple send payment between two customers using list comprehension

 def sendpayment(sender, recipient, amount):

  [(print(x.balance - amount),print(y.balance + amount)) for x in Account.accountList
               for y in Account.accountList
                       if x.name == sender and y.name == recipient]

This works well until I try to see if the new balance has been updated for the two customers, As you can see below once I run A.balance after i run the function sendpayment, Nothing changes on the two customer instances. What I was hoping to achieve was that the balance of the two attributes change once this function is run.

>>> A = Account("Alice", 100)
>>> B = Account("Bob", 50)
>>> Account.sendpayment("Alice", "Bob", 10)
90
60
>>> A.balance
100
>>> B.balance
50

Below is the rest of the code so you get a broad idea of the rest of the customer and account classes in the script.

class Customer:


    def __init__(self, name, balance):
        self.name = name
        self.balance = balance

    def __repr__(self):
        return repr(self.__dict__)

    def __getitem__(self, i):
        return getattr(self, i, )

class Account:

    accountList = []

    def __init__(self, name, balance):
        self.customer = Customer(name, balance)
        Account.accountList.append(self)

    def __repr__(self):
        return repr(self.__dict__)

    def __getitem__(self, i):
        return getattr(self, i)

    def __getattr__(self, attr):

        return getattr(self.customer, attr)


    def sendpayment(sender, recipient, amount):

      [(print(x.balance - amount),print(y.balance + amount)) for x in   Account.accountList
               for y in Account.accountList
                       if x.name == sender and y.name == recipient]
cyclopse87
  • 619
  • 2
  • 11
  • 22
  • 2
    Why would that alter the instances? You're calculating a new value and printing it, there's no assignment. Don't use list comprehensions for side effects, just use regular `for` loops. – jonrsharpe Sep 11 '15 at 20:05
  • I might have mistakenly thought the comprehension is handling the assignment, I thought anything you could do in a for loop you could do in a list comprehension? – cyclopse87 Sep 11 '15 at 20:08
  • Not only are there things you can't do, there are more you shouldn't! A list comp is a good replacement for lots of `append`s, but there are plenty of things that make more sense as conventional loops. – jonrsharpe Sep 11 '15 at 20:10
  • Thanks will bear that in mind in future – cyclopse87 Sep 11 '15 at 20:27

1 Answers1

1
def sendpayment(sender, recipient, amount):
    #first fetch the sender and recipient accounts
    '''Previously had 
    for s in Account.accountList:
        if s.name == sender:
            break
    for r in Account.accountList:
        if r.name == recipient:
            break
    '''
    s = filter(lambda x: x.name == sender, Account.accountList)[0]
    r = filter(lambda x: x.name == recipient, Account.accountList)[0]
    r.balance += amount
    s.balance -= amount
    print(r.balance, s.balance) 
kmad1729
  • 1,484
  • 1
  • 16
  • 20
  • What if `s.balance < amount`? It's not terribly Pythonic to `break` a loop and rely on the loop variable leaking. – jonrsharpe Sep 11 '15 at 20:14
  • I will be putting validation in soon, so it's not possible to send without sender having the amount value, How would you suggest to do the for loop without the variable leak? – cyclopse87 Sep 11 '15 at 20:21
  • removed the break. There can be many ways but I thought it makes sense for a beginner to use breaks. Additional bells and whistles for "amount" etc. might not be the point of the question. – kmad1729 Sep 11 '15 at 20:22
  • That's an awkward way to do it. How about e.g. `next(acc for acc in Account.accountList if acc.name == send)`? Then you don't have to iterate over the whole list and build a new one just to get the first item (which will fail in 3.x where `filter` returns an iterator). But what this really shows is that the fundamental structure is flawed - a mapping `{name: account, ...}` would make the lookup `O(1)` and the code much neater. – jonrsharpe Sep 11 '15 at 20:29
  • @jonrshapre Really appreciate the help, I am totally aware my structure is not perfect, I'm very new to python and am just using this project to practice and learn to code in python I will be looking to make further improvements to the structure hopefully as my proficiency improves. – cyclopse87 Sep 11 '15 at 20:53