在python中,当我取款然后存钱时如何更新余额?

时间:2019-05-03 13:19:56

标签: python python-3.3

我正在使用python代码创建ATM,并且需要创建行为类似于ATM的存款和提取功能。另外,充值和提款功能起作用。但是,当我先提款然后存款时,余额不会更新。当我存入然后取出时,也是一样。

感谢您的帮助。

balance = 600

def withdraw():  # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
    counter = 0
    while counter <= 2:
        while counter == 0:
            withdraw = int(input("Enter the amount you want to withdraw: AED "))
            counter = counter + 1
        while ((int(balance) - int(withdraw)) < 0):
            print("Error Amount not available in card.")
            withdraw = int(input("Please enter the amount you want to withdraw again: AED "))
            continue
        while ((float(balance) - float(withdraw)) >= 0):
            print("Amount left in your account: AED" + str(balance - withdraw))
            return (balance - withdraw)
        counter = counter + 1


def deposit():
    counter = 0
    while counter <= 2:
        while counter == 0:
            deposit = int(input("Enter amount to be deposited: "))
            counter = counter + 1
        while ((int(balance) + int(deposit)) >= 0):
            print("Amount left in your account: AED" + str(balance + deposit))
            return (balance + deposit)
        counter = counter + 1

withdraw()
deposit()

如果我提取17,则余额为583。但是,当我存入12时,余额变为612,这是错误的,应该为595。

5 个答案:

答案 0 :(得分:4)

您根本没有更改“余额”变量! 您的代码应类似于:

balance = withdraw()
balance = deposit()

但是您的代码还有其他多个问题。 首先,您不应该进行那么多的转换。您必须将用户输入一次转换为数字,然后只计算该类型的所有内容。 您正在使用float和int。如果您想充入货币,则应该使用十进制(https://docs.python.org/2/library/decimal.html),因为在某些特殊情况下(需要四舍五入)浮点运算并不精确,而整数显然不提供浮点运算。

您的特殊“ while”用法也不符合常见的编码标准,并且使您的代码难以阅读。最好编写一个函数来获取用户输入并将其与提现()和deposit()逻辑分开。

编辑:由于您似乎是一个初学者,所以我将提供一个最小的可行解决方案。

import decimal

balance = 600

def get_user_input(action):
  # Get user input and convert it to decimal type
  return decimal.Decimal(input("Please enter amount to {} from your account: ".format(action)))

def withdraw():
  amount = get_user_input("withdraw")
  return balance - amount

def deposit():
  amount = get_user_input("deposit")
  return balance + amount

print("Your Balance is {} AED".format(balance))
balance = withdraw()
balance = deposit()
print("Your Balance is {} AED".format(balance))

答案 1 :(得分:2)

您只是忘记保存新余额,而只是打印出

balance = 600

def withdraw():  # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
    while True:
        withdraw = int(input("Enter amount to be withdrawn: "))
        if withdraw > balance:
            print("Error Amount not available in card.")
        else: 
            new_balance = balance - withdraw
            print("Amount left in your account: AED" + str(new_balance))
            return (new_balance)

def deposit():
    deposit = int(input("Enter amount to be deposited: "))
    new_balance = balance + deposit
    print("Amount left in your account: AED" + str(new_balance))
    return (new_balance)

# This is the only place you HAVE to change for it to work
balance = withdraw()
balance = deposit()   

可以自由更改它,但最重要的是,您应该保存新的余额。

我还建议通过在将整数转换为整数之前检查它是否为整数来使整数转换更安全。

        withdraw_string = input("Enter amount to be withdrawn: ")        
        try:
            withdraw_int = int(withdraw_string)
            is_int = True
        except ValueError:
            print("INVALID INPUT")
            is_int = False

        if is_int == True:

答案 2 :(得分:1)

deposit()widthdraw()函数中,您从未真正接触过保持平衡的变量,这就是为什么看不到更改的原因。

您已经定义了变量 balance ,但是您从未使用balance = balance - x更新该值。您仅使用str(balance + deposit)打印该数学运算的结果,该代码实际上并不会改变您的余额。

要更改您的余额,您需要使用balance += widthdraw更新该全局变量。但是,如果将该代码放入代码中,则会出现以下错误:

  

UnboundLocalError:分配前引用了本地变量'balance'

这是因为为了从函数内部更新全局变量,您需要使用 global 关键字,以便可以链接到全局变量。 Docs.

下面的代码现在可以正常工作了,以下两行是重要的:

balance -= withdraw
balance += deposit

这就是您实际上在修改 balance 变量中的值的方法,而不是仅查看数学运算的输出。

balance = 600

def withdraw():  # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
    global balance
    counter = 0
    while counter <= 2:
        while counter == 0:
            withdraw = int(input("Enter the amount you want to withdraw: AED "))
            counter = counter + 1
        while ((int(balance) - int(withdraw)) < 0):
            print("Error Amount not available in card.")
            withdraw = int(input("Please enter the amount you want to withdraw again: AED "))
            continue
        while ((float(balance) - float(withdraw)) >= 0):
            balance -= withdraw
            print("Amount left in your account: AED " + str(balance))
            return (balance)
        counter = counter + 1


def deposit():
    global balance
    counter = 0
    while counter <= 2:
        while counter == 0:
            deposit = int(input("Enter amount to be deposited: "))
            counter = counter + 1
        while ((int(balance) + int(deposit)) >= 0):
            balance += deposit
            print("Amount left in your account: AED" + str(balance))
            return balance
        counter = counter + 1

withdraw()
deposit()

免责声明:您绝对可以从提现存款中删除您的 return语句,因为它们实际上是无用的用这种方式解决问题。为什么没用?因为全局变量 balance 在方法内部被修改。如果您在方法之外修改了余额,则 return语句将很有用。像这样:

balance = 600

def withdraw():  # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
    counter = 0
    while counter <= 2:
        while counter == 0:
            withdraw = int(input("Enter the amount you want to withdraw: AED "))
            counter = counter + 1
        while ((int(balance) - int(withdraw)) < 0):
            print("Error Amount not available in card.")
            withdraw = int(input("Please enter the amount you want to withdraw again: AED "))
            continue
        while ((float(balance) - float(withdraw)) >= 0):
            tmp_balance -= withdraw
            print("Amount left in your account: AED " + str(tmp_balance))
            return tmp_balance
        counter = counter + 1


def deposit():
    counter = 0
    while counter <= 2:
        while counter == 0:
            deposit = int(input("Enter amount to be deposited: "))
            counter = counter + 1
        while ((int(balance) + int(deposit)) >= 0):
            tmp_balance += deposit
            print("Amount left in your account: AED" + str(tmp_balance))
            return tmp_balance
        counter = counter + 1

balance = withdraw()
balance = deposit()

通过第二种方法,您将根据方法提供给您的回报来操纵 balance 的值。此处的区别在于,当您致电提款存款时,实际上并没有执行该操作,只有在您使用{{1 }}。这样做有一个很好的好处,那就是确保没有异常发生,并且如果提现存款完全以100%完成,那么您可以提交更改。

我决定对代码进行进一步介绍,因为您似乎对 int floats 和while循环进行了很多转换。

下面是一个示例,介绍了如何实现该方法,以防给任何人更多的想法:(请记住,代码没有单一的路径,我们的代码都不同)

  • 使用修饰符处理 int()强制转换。您可以在https://www.python.org/dev/peps/pep-0318/上阅读有关装饰器的信息。当您重复执行代码(几乎复制并粘贴)时,通常是应用DRY的标志(请勿重复自己)。您可以通过将责任提取到可以调用的通用函数或使用很棒的Python使用装饰器来应用DRY。因此,装饰器不过是函数,您可以通过简单地放置 @decorator_name 来用它们“装饰”函数。这只是意味着装饰器将在调用装饰函数之前执行。
  • 我不会强制转换为 float ,因为在您的代码中,您总是将输入强制转换为 int()。在这种情况下,余额绝对不能是浮动的。
  • 创建一个名为ATM的类,您可以使用 cash_available 变量实例化该变量,该变量是ATM机中的现金。
  • 删除固定的while循环(计数器= 2),并改用一个循环,让用户退出命令。
  • 提取获取提款方法输入的责任,然后让用户决定是否要再次提款。
  • 由于您使用的是Python 3,请应用balance = withdraw()字符串格式。

现在是代码。

f""

让我们一点一点地经历它。

装饰器是这个。

def exit_on_input_cast_error(func):
def wrapper(arg):
    try:
        return func(arg)
    except ValueError as ex:
        print("Exiting, bye.")
        exit()
return wrapper


class ATM():
"""A simple atm machine"""

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

@exit_on_input_cast_error
def withdraw(self):
    '''Withdraws entered amount, until user exits'''
    continue_withdraw = True
    while continue_withdraw:
        withdraw_amount = self._get_withdraw_input()
        self.cash_available -= withdraw_amount
        self.print_balance("left in")
        withdraw_again = str(input("Would you like to withdraw another amount? (Y or N)"))
        continue_withdraw = withdraw_again.lower() in ['1', 'y', 'yes']
    self.print_bye()

@exit_on_input_cast_error
def _get_withdraw_input(self):
    input_error = True
    while input_error:
        withdrawl = int(input("Enter the amount you want to withdraw (Press N to exit): AED "))

        if (self.cash_available - withdrawl) < 0:
            print("Error Amount not available in machine.")
            input_error = True
        elif (self.cash_available - withdrawl) > self.cash_available:
            print("Error, you can't withdraw a negative amount.")
            input_error = True
        else:
            input_error = False
    return withdrawl

@exit_on_input_cast_error
def deposit(self):
    input_error = True
    while input_error:
        depositing = int(input("Please enter the amount you want to deposit (Press N to exit): AED "))
        if (self.cash_available + depositing) < self.cash_available:
            print("You cannot deposit a negative amount.")
        else:
            input_error = False
            self.cash_available += depositing
    self.print_balance("now in")
    self.print_bye()

def print_balance(self, custom_insert = 'in'):
    print(f"Amount {custom_insert} your account: AED {self.cash_available}")

def print_bye(self):
    print("Thank you for using our services today, bye.")

那只是装饰器的语法。重要的部分是 return func(arg)。这就是将要捕获的功能。因此,此装饰器仅负责捕获 ValueError 异常,当您尝试投射类似def exit_on_input_cast_error(func): def wrapper(arg): try: return func(arg) except ValueError as ex: print("Exiting, bye.") exit() return wrapper 之类的异常时可以抛出该异常。此修饰符旨在防止用户尝试将字符串撤回存放到atm机中。由于这是您将同时用于提款或存款输入的代码,因此我将其放置为装饰器,以便于调用(Hello DRY原理)。

接下来,我们有了类构造器。我希望您熟悉类,如果您不熟悉它们,可以查找很多链接和文档,以了解方法之类的区别你原来有。在这种情况下,最大的优势是您可以拥有多个atm,每个atm拥有不同的现金量。或者,您可以实例化一个ATM类,并为其进行配置,例如语言或硬币类型。这样的东西。

int('a')

用于定义类的就是normal syntax。 “”“简单的atm机”“”是 docstring ,因此,当您调用类 .__ doc __ 时,您会得到回报。

现在有了好东西。

class ATM():
"""A simple atm machine"""

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

此方法用于处理获取用户的输入。看到它如何装饰为 @exit_on_input_cast_error ?这意味着,如果用户输入'a',则程序退出。这是因为@exit_on_input_cast_error def _get_withdraw_input(self): input_error = True while input_error: withdrawl = int(input("Enter the amount you want to withdraw (Press N to exit): AED ")) if (self.cash_available - withdrawl) < 0: print("Error Amount not available in machine.") input_error = True elif (self.cash_available - withdrawl) > self.cash_available: print("Error, you can't withdraw a negative amount.") input_error = True else: input_error = False return withdrawl 强制转换将引发装饰器捕获的 ValueError 异常。该方法以伪代码执行以下操作:

int(...)

基本上就是这种方法的作用。它一直要求用户输入有效的输入,直到用户输入有效的输入,或者输入“ N”退出。以及为什么当他们输入“ N”时退出。由于“ N”不是 int ,因此,在此行中进行强制转换时:

while there's an error do the following:
    Get the user input and cast it as an int. 
    Make sure the amount user has introduced matches the following criteria:
        It is not more than the cash available in the atm.
        It is not a negative number.

int()将引发 ValueError ,然后由方便的装饰器 withdrawl = int(input("Enter the amount you want to withdraw (Press N to exit): AED ")) 捕获异常。然后打印“再见”并为您退出。酷吧?

接下来是您实际使用的提现方法。现在的区别是只有一个循环会继续询问用户是否希望在操作完成后再次退出。由用户决定退出还是再次退出。

@exit_on_input_cast_error

使用伪代码:

@exit_on_input_cast_error
def withdraw(self):
    '''Withdraws entered amount, until user exits'''
    continue_withdraw = True
    while continue_withdraw:
        withdraw_amount = self._get_withdraw_input()
        self.cash_available -= withdraw_amount
        self.print_balance("left in")
        withdraw_again = str(input("Would you like to withdraw another amount? (Y or N)"))
        continue_withdraw = withdraw_again.lower() in ['1', 'y', 'yes']
    self.print_bye()

从本质上讲,这就是方法的作用。它使用了用于打印消息的新方法。

while the user wants to withdraw:
    Get the user input
    Check that the withdraw action does not result in 0 or negative number. 
    Print the balance
    Ask the user if they want to withdraw again.

可以调用这些方法并传递消息的自定义部分,例如 print_balance 。它们显示 ATM 类的私有类变量。在提款方法中,我必须指出,您可以提款直至达到0。这台机器将让您尝试继续提款,但由于其中有0现金,它不会让您提款。 。

最后是存款方法。

def print_balance(self, custom_insert = 'in'):
    print(f"Amount {custom_insert} your account: AED {self.cash_available}")

def print_bye(self):
    print("Thank you for using our services today, bye.")
如您所见,

非常简单并且遵循相同的原理。这是调用实际方法的方式:

@exit_on_input_cast_error
def deposit(self):
    input_error = True
    while input_error:
        depositing = int(input("Please enter the amount you want to deposit (Press N to exit): AED "))
        if (self.cash_available + depositing) < self.cash_available:
            print("You cannot deposit a negative amount.")
        else:
            input_error = False
            self.cash_available += depositing
    self.print_balance("now in")
    self.print_bye()

这是代码的输出:

atm_a = ATM(600)
atm_a.withdraw()

如果您要提款和存款:

Enter the amount you want to withdraw (Press N to exit): AED 100
Amount left in your account: AED 500
Would you like to withdraw another amount? (Y or N)Y
Enter the amount you want to withdraw (Press N to exit): AED -1
Error, you can't withdraw a negative amount.
Enter the amount you want to withdraw (Press N to exit): AED 501
Error Amount not available in machine.
Enter the amount you want to withdraw (Press N to exit): AED 5
Amount left in your account: AED 495
Would you like to withdraw another amount? (Y or N)yes
Enter the amount you want to withdraw (Press N to exit): AED 5
Amount left in your account: AED 490
Would you like to withdraw another amount? (Y or N)no
Thank you for using our services today, bye.

以下是代码的输出:

atm_a = ATM(600)
atm_a.withdraw()
atm_a.deposit()

请注意,您只能存入一次,然后存入。那是因为我没有实现它,因为我已经为提现做过。任何人都可以根据需要在存款中复制它。

我希望这不是太多,我设法解释了一下。有很多事情无法添加:

  • 测试用例
  • ATM现金和用户帐户余额之间的差异
  • 在提款时,要知道您是否有正确数量的账单以提供所需的金额 ...等

答案 3 :(得分:0)

我同意@Chetan Ranpariya的建议,您尚未在代码中同时更改两个函数的balance变量。您可以使用表达式balancebalance += <increase amount>balance -= <decrease amount>等来更改balance = balance + <increase amount>变量。

balance = 600

def withdraw():  # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
    counter = 0
    while counter <= 2:
        while counter == 0:
            withdraw = int(input("Enter the amount you want to withdraw: AED "))
            counter = counter + 1
        while ((int(balance) - int(withdraw)) < 0):
            print("Error Amount not available in card.")
            withdraw = int(input("Please enter the amount you want to withdraw again: AED "))
            continue
        while ((float(balance) - float(withdraw)) >= 0):
            print("Amount left in your account: AED" + str(balance - withdraw))
            return (balance - withdraw)
        counter = counter + 1


def deposit():
    counter = 0
    while counter <= 2:
        while counter == 0:
            deposit = int(input("Enter amount to be deposited: "))
            counter = counter + 1
        while ((int(balance) + int(deposit)) >= 0):
            print("Amount left in your account: AED" + str(balance + deposit))
            return (balance + deposit)
        counter = counter + 1

balance = withdraw()
balance = deposit()

答案 4 :(得分:0)

您没有更改balance变量,仅返回添加或减少了depositwithdraw的值。

尝试更改您的代码,以便在返回之前保存新的balance。所以代替:

print("Amount left in your account: AED" + str(balance - withdraw))
return (balance - withdraw)

尝试:

balance = (balance - withdraw)
print("Amount left in your account: AED" + str(balance))
return balance

然后使用deposit函数进行相同操作。

您的新代码:

balance = 600

def withdraw():  # asks for withdrawal amount, withdraws amount from balance, returns the balance amount
    counter = 0
    while counter <= 2:
        while counter == 0:
            withdraw = int(input("Enter the amount you want to withdraw: AED "))
            counter = counter + 1
        while ((int(balance) - int(withdraw)) < 0):
            print("Error Amount not available in card.")
            withdraw = int(input("Please enter the amount you want to withdraw again: AED "))
            continue
        while ((float(balance) - float(withdraw)) >= 0):
            balance = (balance - withdraw)
            print("Amount left in your account: AED" + str(balance))
            return balance
        counter = counter + 1


def deposit():
    counter = 0
    while counter <= 2:
        while counter == 0:
            deposit = int(input("Enter amount to be deposited: "))
            counter = counter + 1
        while ((int(balance) + int(deposit)) >= 0):
            balance = (balance + deposit)
            print("Amount left in your account: AED" + str(balance))
            return balance
        counter = counter + 1

withdraw()
deposit()