[英]Update assigned variable used in multiple functions using a while loop - PYTHON
I completed an assignment for a scripting class I'm taking, and it worked fine, but I wanted to take it a step further, which has sent me down a rabbit hole.我完成了我正在接受的脚本 class 的作业,它运行良好,但我想更进一步,这让我陷入了困境。 The script is for an ATM transaction.
该脚本用于 ATM 交易。
I added a while loop to give the user additional options, instead of just ending the program.我添加了一个 while 循环来为用户提供额外的选项,而不是仅仅结束程序。 But I found the my account_balance variable remained equal to the default value set initially (in this case 500.25).
但我发现我的 account_balance 变量仍然等于最初设置的默认值(在本例中为 500.25)。 I've been trying to find ways to make this update as the user goes through the program, in theory it should go as follows:
当用户通过程序时,我一直试图找到进行此更新的方法,理论上它应该 go 如下:
To try and make this work, I made another function transactionGo(pin), and set all the other functions inside it, hoping this would update the variable account_balance, that didn't work either, and in fact caused more problems, I feel I'm going down a road I shouldn't.为了尝试使这项工作,我制作了另一个 function transactionGo(pin),并在其中设置了所有其他函数,希望这会更新变量 account_balance,这也不起作用,实际上引起了更多问题,我觉得我正在走一条我不应该走的路。
import sys
# -------------------------- DECLARE variables for balance, deposit, and withdrawal --------------------------
account_balance = float(500.25) # Starting balance indicated by Codio
#balance = 100
amount = 0
#deposit_amount = 0 # Declare variable 'deposit_amount'
#withdrawal_amount = 0 # Declare variable 'withdrawal_amount'
pin = ''
# -------------------------- DEFINE FUNCTIONS - balance, withdrawal, and deposit -----------------------------
def transactionGo (pin):
pin = int(input("Please enter your 5 digit pin number:\n"))
def balance(account_balance): # Define balance function
print("Your current balance is $%.2f" % (account_balance)) # Prints the current available balance
def deposit(account_balance, amount): # Define DEPOSIT function with parameters account_balance and amount
amount = float(input("How much would you like to deposit today?\n")) # Accept user input for the deposit amount, in float format
balance = account_balance + amount # This addition assigns the updated value of the account balance, to the variable 'account_balance'
print("Deposit was $%.2f , your new current balance is $%.2f" % (amount, balance)) # Prints deposit amount and account balance
return balance # Return records the new value of account_balance to reflect accordingly in other transactions
def withdrawal(account_balance, amount): # Define WITHDRAWAL function with parameters account_balance and withdrawal_amount
amount = float(input("How much would you like to withdraw today?\n")) # Accept user input for the withdrawal amount, in float format
if amount > account_balance: # Checking to see if the amount requested, is greater than the amount available
print("Insufficient funds, $%.2f is greater than your account balance of $%.2f" % (amount, account_balance)) # If the amount requested is greater than the account balance, there are insufficient funds
else: # Sufficient amount of funds are available, the function continues
balance = account_balance - amount # Variable 'balance' is assigned to reflect the new available balance
print ("Withdrawal amount was $%.2f, your new current balance is $%.2f" % (amount, balance)) # Prints withdrawal amount and account balance
return balance # Return records the new value of balance to reflect accordingly in other transactions
# Lines 18 and 20 compose a conditional statement with the withdrawal function
# Line 18 => if the requested withdrawal amount is greater than the account balance, the conditional statement stops, and prints to the user there are insufficient funds
# Line 20 => if there are sufficient funds available, the conditional statement continues, updates the 'balance', and outputs to the user their withdrawal amount and new available balance
# ------------------------------------ ACCEPT USER INPUT - D, B, W, or Q -------------------------------------
userAccess = input ("Welcome to Tom & Kate Banking, if you would like to sign into your account, please press (C)ontinue, or (E)xit\n").upper()
if userAccess == 'C':
transactionGo (pin)
userChoice = 'go' # Setting the variable 'userChoice' to 'go', so we can implement a while loop
# Step ONE => Create a WHILE loop to offer the user additional options after they have completed a transaction
while userChoice != 'E': # As long as the user does not select 'E' (Exit), the program will keep looping with user choices
# Step TWO => Ask user what action they would like to proceed with, user input is accepted and assigned to the variable 'userchoice'
userChoice = input ("Would you like to check your (B)alance, make a (D)eposit, (W)ithdraw cash, or (E)xit?\n").upper()
# Step THREE => conditional statement begins based on the value of variable 'userchoice' from user input
# Four branches utilizing if / elif for DEPOSIT, BALANCE, WITHDRAWAL, EXIT
if (userChoice == 'D'): # Accepts input D and proceeds with function 'deposit'
deposit (account_balance, amount) # DEPOSIT function is called with parameters 'balance' and 'amount'
elif (userChoice == 'B'): # Accepts input B and proceeds with function 'balance'
balance (account_balance) # BALANCE function is called with parameter 'balance'
elif (userChoice == 'W'): # Accepts input D and proceeds with function 'withdrawal'
withdrawal (account_balance, amount) # WITHDRAWAL function is called with parameters 'balance' and 'amount'
elif (userChoice == 'E'): # Accepts input E for EXIT
print("Thank you for banking with us.") # There is no function for EXIT, and therefore the user has a printed message ending their session
else:
print("We hope to see you again soon, have a nice day!")
When I run this, the first function runs - transactionGo(pin), but when I go into the other transaction functions, IDLE tells me my variables are undefined.当我运行它时,第一个 function 运行 - transactionGo(pin),但是当我 go 进入其他事务函数时,IDLE 告诉我我的变量未定义。
PROBLEM: The scope of the account_balance variable and the functions within transactionGo are different to how you are using them.问题:account_balance 变量的 scope 和 transactionGo 中的函数与您使用它们的方式不同。 For example, if you wish to modify a variable outside of a function you need to declare it global at the top of your function definition.
例如,如果您希望修改 function 之外的变量,则需要在 function 定义的顶部将其声明为全局变量。
Furthermore, the functions within transactionGo cannot be accessed anywhere in the file except for the transactionGo function itself as the scope of the functions is just within the transactionGo function and not anywhere else.此外,除了 transactionGo function 本身之外,不能在文件中的任何位置访问 transactionGo 中的函数,因为函数的 scope 就在 transactionGo ZC1C425268E68385D1AB5074C17A94F14 中,而不是其他任何地方。 This is why IDLE tells you the functions are undefined, because they are not a part of the file but a part of the transactionGo function and inside of that function only.
这就是为什么 IDLE 告诉你函数是未定义的,因为它们不是文件的一部分,而是 transactionGo function 和 function 内部的一部分。 So in your code those functions are never called
所以在你的代码中,这些函数永远不会被调用
SOLUTIONS: You need to ensure you understand scope in python.解决方案:您需要确保您了解 python 中的 scope。 The following link is an amazing explanation of what is meant by scope:
以下链接是对 scope 含义的惊人解释:
https://www.w3schools.com/python/python_scope.asp https://www.w3schools.com/python/python_scope.asp
In the following methods used to solve this issue, I will assume you want the functions themselves to change and modify the banking variables themselves.在用于解决此问题的以下方法中,我将假设您希望函数本身更改和修改银行变量本身。
Method #1 : Using the 'global' keyword and fixing the functions scopes方法#1 :使用'global'关键字并修复函数范围
# Describe the problem
# How to learn more about the problem
# Full solutions explained.
import sys
# -------------------------- DECLARE variables for balance, deposit, and withdrawal --------------------------
account_balance = float(500.25) # Starting balance indicated by Codio
#balance = 100
amount = 0
#deposit_amount = 0 # Declare variable 'deposit_amount'
#withdrawal_amount = 0 # Declare variable 'withdrawal_amount'
pin = ''
# -------------------------- DEFINE FUNCTIONS - balance, withdrawal, and deposit -----------------------------
def transactionGo (pin):
pin = int(input("Please enter your 5 digit pin number:\n"))
def balance(account_balance): # Define balance function
print("Your current balance is $%.2f" % (account_balance)) # Prints the current available balance
def deposit(): # Define DEPOSIT function with parameters account_balance and amount
global account_balance # Using the 'global' keyword allows you to edit and modify the value of account_balance
amount = float(input("How much would you like to deposit today?\n")) # Accept user input for the deposit amount, in float format
account_balance += amount # This addition assigns the updated value of the account balance, to the variable 'account_balance'
print("Deposit was $%.2f , your new current balance is $%.2f" % (amount, account_balance)) # Prints deposit amount and account balance # Return records the new value of account_balance to reflect accordingly in other transactions
def withdrawal(): # Define WITHDRAWAL function with parameters account_balance and withdrawal_amount
global account_balance
amount = float(input("How much would you like to withdraw today?\n")) # Accept user input for the withdrawal amount, in float format
if amount > account_balance: # Checking to see if the amount requested, is greater than the amount available
print("Insufficient funds, $%.2f is greater than your account balance of $%.2f" % (amount, account_balance)) # If the amount requested is greater than the account balance, there are insufficient funds
else: # Sufficient amount of funds are available, the function continues
account_balance -= amount # Variable 'balance' is assigned to reflect the new available balance
print ("Withdrawal amount was $%.2f, your new current balance is $%.2f" % (amount, account_balance)) # Prints withdrawal amount and account balance
return balance # Return records the new value of balance to reflect accordingly in other transactions
# Lines 18 and 20 compose a conditional statement with the withdrawal function
# Line 18 => if the requested withdrawal amount is greater than the account balance, the conditional statement stops, and prints to the user there are insufficient funds
# Line 20 => if there are sufficient funds available, the conditional statement continues, updates the 'balance', and outputs to the user their withdrawal amount and new available balance
# ------------------------------------ ACCEPT USER INPUT - D, B, W, or Q -------------------------------------
userAccess = input ("Welcome to Tom & Kate Banking, if you would like to sign into your account, please press (C)ontinue, or (E)xit\n").upper()
if userAccess == 'C':
transactionGo (pin)
userChoice = 'go' # Setting the variable 'userChoice' to 'go', so we can implement a while loop
# Step ONE => Create a WHILE loop to offer the user additional options after they have completed a transaction
while userChoice != 'E': # As long as the user does not select 'E' (Exit), the program will keep looping with user choices
# Step TWO => Ask user what action they would like to proceed with, user input is accepted and assigned to the variable 'userchoice'
userChoice = input ("Would you like to check your (B)alance, make a (D)eposit, (W)ithdraw cash, or (E)xit?\n").upper()
# Step THREE => conditional statement begins based on the value of variable 'userchoice' from user input
# Four branches utilizing if / elif for DEPOSIT, BALANCE, WITHDRAWAL, EXIT
if (userChoice == 'D'): # Accepts input D and proceeds with function 'deposit'
deposit () # DEPOSIT function is called with parameters 'balance' and 'amount'
elif (userChoice == 'B'): # Accepts input B and proceeds with function 'balance'
balance (account_balance) # BALANCE function is called with parameter 'balance'
elif (userChoice == 'W'): # Accepts input D and proceeds with function 'withdrawal'
withdrawal () # WITHDRAWAL function is called with parameters 'balance' and 'amount'
elif (userChoice == 'E'): # Accepts input E for EXIT
print("Thank you for banking with us.") # There is no function for EXIT, and therefore the user has a printed message ending their session
else:
print("We hope to see you again soon, have a nice day!")
BankAccount.py银行账户.py
# This file will contain the class, to keep our project organised
class BankAccount:
def __init__(self, account_balance, pin):
self.account_balance = account_balance # The account_balance is a class attribute
self.pin = pin # Class attribute
def __repr__(self):
return f'Account Balance: {self.account_balance}, Pin: {pin}'
def check_pin(self):
number_of_tries = 3 # Number of pin tries the user gets
for i in range(number_of_tries, 0, -1): # Counts backwards from the number_of_tries to the last digit 0
print(f'Number of attempts remaining: {i}')
while True:
try:
inputted_pin = input('Please enter your 5 digit pin number:\n')
if len(inputted_pin) != 5: # Checks and then handles whether or not the pin is 5 digits
incorrect_pin_length_error_message = 'Please ensure the pin you enter is 5 digits long\n\n'
print(incorrect_pin_length_error_message)
inputted_pin = int(inputted_pin)
if inputted_pin == self.pin: # If the valid pin is the actual pin of this bank account
return True # Allows the user to enter
else:
break # Breaks out of the while loop making onto the next iteration of the for loop
except ValueError: # If the pin entered contains any character that is not a number then this except block will be hit when int(inputted_pin) is called
did_not_enter_all_numbers_error_message = 'Please ensure that you have entered pin number.\n\n'
print(did_not_enter_all_numbers_error_message)
# If there is an error in the way a pin was entered it does not count as an attempt
# Only when the pin is valid does it use up an attempt
return False # Returns False if the user fails to input the correct pin in the number of tries given
def check_balance(self):
"""
Prints the balance of the bank account.
"""
print('Your current balance is $%.2f\n' % self.account_balance)
def make_deposit(self):
try:
amount_to_deposit = input('How much would you like to deposit today?\n')
try:
if len(amount_to_deposit.split('.')[1]) != 2: # Checks whether or not the user inputted two decimal places and two decimals only
more_than_two_decimal_place_error_message = 'Please ensure that your deposit is to two decimal places only.\n\n'
print(more_than_two_decimal_place_error_message)
else:
if amount_to_deposit.count('.') > 1: # Ensures that there is not more than one decimal point in the given input
multiple_decimal_points_error_message = 'Please ensure that the amount you wish to withdraw does not have multiple decimal points.\n\n'
print(multiple_decimal_points_error_message)
else:
self.account_balance += float(amount_to_deposit) # Adds the amount once validated
self.check_balance() # Prints out the current balance of the user
except IndexError: # Occurs if the user does not enter a decimal point
did_not_enter_two_decimal_places_error_message = 'Please ensure that you enter exactly two decimal places in your deposit.\n\n'
print(did_not_enter_two_decimal_places_error_message)
except ValueError: # Ensures that the input are all numbers
did_not_enter_number_error_message = 'Please ensure that you enter a numerical amount.\n\n'
def make_withdrawal(self):
try:
amount_to_withdraw = input('How much would you like to withdraw today?\n')
if len(amount_to_withdraw.split('.')[1]) != 2: # Ensures that there are two decimal places inputted and hta
more_than_two_decimal_place_error_message = 'Please ensure that your withdrawal is to two decimal places only.\n\n'
print(more_than_two_decimal_place_error_message)
else:
if amount_to_withdraw.count('.') > 1: # Ensures that there is not more than one decimal point in the given input
multiple_decimal_points_error_message = 'Please ensure that the amount you wish to withdraw does not have multiple decimal points.\n\n'
print(multiple_decimal_points_error_message)
else:
amount_to_withdraw = float(amount_to_withdraw)
if amount_to_withdraw > self.account_balance: # Ensures that the user has enough funds to withdraw money from
insufficient_funds_message = 'Insufficient funds, $%.2f is greater than your account balance of $%.2f' % (amount_to_withdraw, self.account_balance)
else:
self.account_balance -= amount_to_withdraw # Once validated withdraws the amount from the account
self.check_balance() # Prints the user's balance
except ValueError: # Ensures that the input is only numbers
did_not_enter_number_error_message = 'Please ensure that you enter a numerical amount.\n\n'
def exit_transaction():
exit_message = 'Thank you for banking with us.'
print(exit_message)
def do_transaction():
# The main loop that you defined in your original code.
if self.check_pin():
while True:
user_choice = input('Would you like to check your (B)alance, make a (D)eposit, (W)ithdraw cash, or (E)xit?\n').upper()
if user_choice == 'B':
self.check_balance()
elif user_choice == 'D':
self.make_deposit()
elif user_choice == 'W':
self.make_withdrawal()
elif user_choice == 'E':
self.exit_transaction()
else:
unsuccessful_pin_error_message = 'It seems like you ran out of pin tries, please try again later.'
print(unsuccessful_pin_error_message)
main.py主文件
from BankAccount import BankAccount
person1_bank_account = BankAccount(account_balance=500.25, pin=12345)
person2_bank_account = BankAccount(account_balance=1100.00, pin=54321)
# As many as you want
# Perform any functions on them
person1_bank_account.make_deposit()
person2_bank_account.make_withdrawal()
# Print values
print(person1_bank_account.account_balance)
print(person2_bank_account.pin)
This way your code is more flexible, clean, and scalable.这样,您的代码就更加灵活、简洁和可扩展。 For example in your class you can add ass many methods as you want in whatever way you want, and every instance of that class gains that functionality on top of being easy to manage.
例如,在您的 class 中,您可以以任何您想要的方式添加任意数量的方法,并且该 class 的每个实例除了易于管理之外还获得了该功能。 You can handle any exception you want in whatever way you want.
你可以用任何你想要的方式处理你想要的任何异常。 So this is what I would suggest.
所以这就是我的建议。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.