Ask coding questions

← Back to all posts
Need Help
AimanFayaz (6)

Hi there! I am a novice python programmer. I have recently taken a course on Udemy and then started to make a project on my own idea. It is a bank, where you can create accounts, deposit money, invest in schemes etc. However, I am getting an error with calling nonlocal variables. Here is my entire code.

import keyboard
import time
import sys
import random

Code = random.randint(1000,5001)
int(Code)
AccountCreated = False #If ANY account is created
StandardAccountCreated = False #If Standard account is created
EliteAccountCreated = False #If Elite account is created
balance = 50000
F = 0 #Number of Menu chosen
Answer = 0 #Type of account chosen
Standard = Elite = Executive = 0 #Status of different accounts
Acc = 0 #Whether an account is to be opened or not


#The Main Menu

print("Welcome to the CITY BANK. We provide a wide range of services including balance checks, several types of accounts, investment options and\nmuch more!.")
time.sleep(2)
print("Please type the corresponding number below in order to access our services.")
time.sleep(1)

def MainMenu(): #This is the list of services the user can access
    print("\n1. Create/Access your account.\n2. Check our investment options.\n3. Check your balance.\n4. Exit.")
    time.sleep(1)
    def SelectionMenu(): #The User selects the server they wish to access
        F = input("\nType the number of the service you wish to access:")
        
        #Account Creator
        
        if (F == "1" and AccountCreated == False):
            Acc = input("You currently do not have an account in our bank. Would you like to create one? (Y/N):")
            if (Acc == "Y"):
                print("Great! Here are your available options:")
                
                time.sleep(0.5)
                print("\n1. Standard Account\nYou will be able to deposit a total of 1,000,000 USD with an annual interest rate of 2%.\nIt will cost you 400 USD initially. No extra perks included.")
                
                time.sleep(0.5)
                print("\n2. Elite Account\nYou will be able to deposit a total of 1,5000,000 USD with an annual interest rate of 2%.\nIt will cost you 650 USD initially. You will also have access to a free vault at 500,000 USD deposited.")
            
            def Accountchooser():    
                time.sleep(1)
                Answer = input("\nEnter the number of your desired account type here:")
                
                #Standard Account Profile Form
                    
                if (Answer == "1"):
                    print("Great! So you have chosen to open a standard account with our bank! It will cost you 400 USD. Please answer the following the questions to create your account.\nIf this was a mistake, type 'Back' in the place of your name.")
                    time.sleep(1)
                    NameStandard = input("Type your full name:")
                    if (NameStandard == "Back" or NameStandard == "back"):
                         Accountchooser()
                         NameStandard = 0
                    AgeStandard = input("Type your age:")
                    EmailStandard = input("Type your email address:")
                    
                    # Standard Created profile Info

                    time.sleep(2)
                    print("Your profile has been created! Your details are provided below:\nName: " + str(NameStandard) + ".")
                    print("Age: " + str(AgeStandard) + ".")
                    print("Email Address: " + str(EmailStandard) + ".")
                    print("Your account code is " + str(Code))
                    print("Please keep your personal code hidden, it will be used for accessing your account later.")
                    

                    #StandardBackToMenu
                        
                    def StandardTryAgain():
                        StandardBackToMenu = input("Please type 'P' for going back to the menu:")
                        if (StandardBackToMenu == "P"):
                            global balance
                            balance = balance - 400
                            global AccountCreated
                            AccountCreated = True
                            global StandardAccountCreated
                            StandardAccountCreated = True
                            MainMenu()
                                
                        else:
                            print("Wrong Answer, please type again.")
                            StandardTryAgain()
                    StandardTryAgain()
                        
                #Elite Account Creator
                
                elif (Answer == "2"):
                    print("Great! So you have chosen to open a elite account with our bank! It will cost you 650 USD. Please answer the following the questions to create your account.\nIf this was a mistake, type 'Back' in the place of your name.")
                    time.sleep(1)
                    NameElite = input("Type your full name:")
                    if (NameElite == "Back" or NameElite == "back"):
                         Accountchooser()
                         NameElite = 0
                    AgeElite = input("Type your age:")
                    EmailElite = input("Type your email address:")
                    
                    # Elite Created profile Info

                    time.sleep(2)
                    print("Your profile has been created! Your details are provided below:\nName: " + str(NameElite) + ".")
                    print("Age: " + str(AgeElite) + ".")
                    print("Email Address: " + str(EmailElite) + ".")
                    print("Your account code is " + str(Code))
                    print("Please keep your personal code hidden, it will be used for accessing your account later.")
                    

                    #EliteBackToMenu
                        
                    def EliteTryAgain():
                        EliteBackToMenu = input("Please type 'P' for going back to the menu:")
                        if (EliteBackToMenu == "P"):
                            global balance
                            balance = balance - 650
                            global AccountCreated
                            AccountCreated = True
                            EliteAccountCreated = True
                            MainMenu()
                                
                        else:
                            print("Wrong Answer, please type again.")
                            EliteTryAgain()
                    EliteTryAgain()
                
                #Wrong Answer
                
                else:
                    print("Wrong alphabet, please try again.")
                    Accountchooser()
            
            Accountchooser()

            if (Acc == "N"):
                print("Alright then.")
                MainMenu()

        #Accessing the account
        
        elif (F == "1" and AccountCreated == True and StandardAccountCreated == True):
            Nonlocal NameStandard
            Nonlocal AgeStandard
            Nonlocal EmailStandard
            Nonlocal Code
            print("Name: " + str(NameStandard) + ".")
            print("Age: " + str(AgeStandard) + ".")
            print("Email Address: " + str(EmailStandard) + ".")
            print("Your account code is " + str(Code))
            print("Please keep your personal code hidden, it will be used for accessing your account later.")
            def StandardAccountBackerfunc():
                StandardAccountBacker = input("Type 'P' for returning to the main menu.")
                if (StandardAccountBacker == "P"):
                    MainMenu()
                else:
                    print("Wrong answer, please try again.")
                    StandardAccountBackerfunc()
            StandardAccountBackerfunc()

                  
        
        
        #Investion Options Checker
        
        elif (F == "2"):
            print("Bye")

        #Balance Checker
        
        elif (F == "3"):
            print("Your current balance is " + str(balance))
            def BalanceMenu():
                BalanceBackToMenu = input("Type 'B' to go back to the menu:")
                if (BalanceBackToMenu == "B"):
                    MainMenu()
                    int(balance)
                else:
                    print("Wrong answer, please type again.")
                    BalanceMenu()
            BalanceMenu()

        #Exit Console
        
        elif (F == "4"):
            print("ok")
            sys.exit()

        else:
            print("please try again.")
            SelectionMenu()

    SelectionMenu()

MainMenu()

After creating my standard account, whenever I try to access the account afterward, it gives an error saying:

File "main.py", line 142
nonlocal NameStandard
^
SyntaxError: no binding for nonlocal 'NameStandard' found

What is my fault here? :/

NB: I know this code is too big, I had posted this somewhere before with only 2 parts of code, one of which contains the variables and the other calls them, but one of the replies mentioned that only those 2 parts are not enough to figure out the mistake, so I just pasted the entire thing. Please help me :)

Comments
hotnewtop
Coder100 (18057)

You never actually defined nameStandard. nonlocal is used by python for something called closures, but you never provided a valid variable for it to closure to. So do this:

def MainMenu():
  NameStandard = ""
  AgeStandard = ""
  EmailStandard = ""
  Code = ""
  ...
  def SelectionMenu():
    ...
    elif (...):
      nonlocal NameStandard
      nonlocal AgeStandard
      nonlocal EmailStandard
      nonlocal Code

or just replace nonlocal with the global keyword.

AimanFayaz (6)

@Coder100 But what about this piece of code?

if (Answer == "1"):
                    print("Great! So you have chosen to open a standard account with our bank! It will cost you 400 USD. Please answer the following the questions to create your account.\nIf this was a mistake, type 'Back' in the place of your name.")
                    time.sleep(1)
                    NameStandard = input("Type your full name:")
                    if (NameStandard == "Back" or NameStandard == "back"):
                         Accountchooser()
                         NameStandard = 0
                    AgeStandard = input("Type your age:")
                    EmailStandard = input("Type your email address:")

Doesn`t this define the following variables?

Coder100 (18057)

no, because it doesn't define it in the parent function. @AimanFayaz

AimanFayaz (6)

@Coder100 Then how can I keep the variables value the same as the input values if I follow your previous solution?

Coder100 (18057)

make a copy of the variable

namecpy = namestandard

@AimanFayaz

AimanFayaz (6)

@Coder100 Where should I make the copy? I mean in which function or part of the code?

Coder100 (18057)

wherever you need to use it @AimanFayaz

AimanFayaz (6)

@Coder100 Um, so I made 4 new variables in the accessing account part of the code, above the print lines. I then made them equal to the input values of the 4 previous variables. Then, I changed the print values according to them, but the problem is still there :/. That part of the code is given below:

elif (F == "1" and AccountCreated == True and StandardAccountCreated == True):
            global NameStandard
            global AgeStandard
            global EmailStandard
            global Code
            ANameStandard = NameStandard
            AAgeStandard = AgeStandard
            AEmailStandard = EmailStandard
            ACode = Code
            
            print("Name: " + str(ANameStandard) + ".")
            print("Age: " + str(AAgeStandard) + ".")
            print("Email Address: " + str(AEmailStandard) + ".")
            print("Your account c6ode is " + str(ACode))
            print("Please keep your personal code hidden, it will be used for accessing your account later.")
            def StandardAccountBackerfunc():
                StandardAccountBacker = input("Type 'P' for returning to the main menu.")
                if (StandardAccountBacker == "P"):
                    MainMenu()
                else:
                    print("Wrong answer, please try again.")
                    StandardAccountBackerfunc()
            StandardAccountBackerfunc()

Also, I have tried using nonlocal instead of global as well but the same error is shown:

Traceback (most recent call last):
File "e:\BotHello\Learning.py", line 201, in <module>
MainMenu()
File "e:\BotHello\Learning.py", line 199, in MainMenu
SelectionMenu()
File "e:\BotHello\Learning.py", line 135, in SelectionMenu
Accountchooser()
File "e:\BotHello\Learning.py", line 88, in Accountchooser
StandardTryAgain()
File "e:\BotHello\Learning.py", line 83, in StandardTryAgain
MainMenu()
File "e:\BotHello\Learning.py", line 199, in MainMenu
SelectionMenu()
File "e:\BotHello\Learning.py", line 148, in SelectionMenu
ANameStandard = NameStandard
NameError: name 'NameStandard' is not defined

What should I do now?

And really sorry for disturbing you.