Dictionaries in a if statement arent working - python

When I print my Clients dictionary keys using option 2, it shows up as [] even when I've already added a client. Can anyone help me understand what is going wrong?
def main():
import sys
Clients = {}
choice = input(" Click 1 to add another client\n Click 2 to Check a Clients Balance\n Click 3 to change a Clients Balance ")
if choice == "1":
name = input('Add a Client\'s name : ')
Clients.update({name.rstrip("\n"):0})
print(name)
print(Clients.keys())
main()
elif choice == "2":
print(Clients.keys())
main()
elif choice == "3":
print('Do it later')
main()
else:
print('Please choose again')
main()
main()

You are calling main again and again, using a new dictionary each time, this is called recursion. Here, you should use a while loop.
def main():
clients = {}
while True:
choice = input("Click 1 to add another client\n Click 2 to Check a Clients Balance\n Click 3 to change a Clients Balance ")
if choice == "1":
name = input("Add a Client's name : ")
clients[name.rstrip()] = 0
print(name)
print(clients.keys())
elif choice == "2":
print(clients.keys())
elif choice == "3":
print('Do it later')
else:
print('Please choose again')
main()

Related

Python - How do I get the defined variable from one function to another function?

I have simplified it to this:
def hang():
p = 1
while p == 1:
gameinput = input("Please select a gamemode, Type [1] for one player or Type [2] for two player: ")
if gameinput == "2":
def two_player_word():
print("2")
elif gameinput == "1":
def one_player_word():
print("1")
def hangman():
if gameinput == "2":
word = two_player_word()
elif gameinput == "1":
word = one_player_word()
print("Word")
def main():
gamerestart = 1
while gamerestart == 1:
print()
print("Would you like to play again?")
gameoverinput = input("Press [1] to play again, Press [2] to exit program. ")
if gameoverinput == "1":
for i in range(0, 25):
print()
hangman()
elif gameoverinput == "2":
print("Thank you for playing, goodbye....")
time.sleep(2)
quit()
else:
print("Invaild option.")
if __name__ == "__main__":
main()
I had previously defined gameinput in the 'hang()' it collects the user input and so on.
My problem is in the 'hangman()' I need gameinput again to make the variable word (its made so a user can either make a word (two_player_word) or one player when it generates a random word (one_player_word()
It works perfectly without gameinput being in a function but after the player either wins or loses I want it to let the user decide if they want to change gamemode or not as shown in main().
There is a lot more code but figured it would be easier to try figure out the problem using just this.
Just pass the gameinput from hang into hangman as an argument.
def hang():
while True:
gameinput = input("Please select a gamemode, Type [1] for one player or Type [2] for two player: ")
if gameinput not in ("1", "2"):
continue
hangman(gameinput)
break
def hangman(gameinput):
if gameinput == "2":
word = two_player_word()
elif gameinput == "1":
word = one_player_word()
print("Word")
There are two problems that cause your code to fail (besides indentation).
You are defining nested functions (one/two_player_word) which you then try to call from outside the function (where they are not defined). You can change this by defining the functions outside the function hang().
hangman() uses the gameinput variable but it's not defined nor provided. You can change this by adding it as a parameter to the function call.
Your adjusted code could work like this:
import time
def one_player_word():
print("1")
def two_player_word():
print("2")
def hang():
p = 1
while p == 1:
gameinput = input("Please select a gamemode, Type [1] for one player or Type [2] for two player: ")
if gameinput == "2":
two_player_word()
elif gameinput == "1":
one_player_word()
def hangman(gameinput):
if gameinput == "2":
word = two_player_word()
elif gameinput == "1":
word = one_player_word()
print("Word")
def main():
gamerestart = 1
while gamerestart == 1:
print()
print("Would you like to play again?")
gameoverinput = input("Press [1] to play again, Press [2] to exit program. ")
if gameoverinput == "1":
for i in range(0, 25):
print()
hangman(gameoverinput)
elif gameoverinput == "2":
print("Thank you for playing, goodbye....")
time.sleep(2)
quit()
else:
print("Invaild option.")
if __name__ == "__main__":
main()

UnboundLocalError while accessing option 2 in a choice menu

I have been trying different code combinations for three days now and I figured before i throw in the towel this might be a good place to ask my question. In my code, no matter how I try to declare the lists I've been unsuccessful. My problem currently is:
line 54, in main
inputExpenseAmounts(expenseItems)
UnboundLocalError: local variable 'expenseItems' referenced before assignment
import matplotlib.pyplot as plt
from prettytable import PrettyTable
def menu():
print('[1] Enter Expense Name')
print('[2] Enter Expense Amount')
print('[3] Display Expense Report')
print('[4] Quit')
choice = input('Enter choice: ')
return choice
def inputExpenseNames():
expenseItems = []
name = input("Enter expense name (q for quit) \n")
while name != "q" :
expenseItems.append(name)
name = input("Enter expense name (q for quit) \n")
return expenseItems
def inputExpenseAmounts(expenseItems):
expenseAmounts = []
print("Enter the amount for each expense ")
for i in expenseItems:
amount = int(input(i + " : "))
expenseAmounts.append(amount)
return ExpenseAmounts
def displayExpenseReport(expenseItems, expenseAmounts):
displayExpenseReport = []
option = input("Display in \n (a) table \n (b) bar chart \n (c) pie chart \n")
if option == "c":
plt.pie(expenseAmounts, labels = expenseItems)
plt.show()
elif option == "b":
plt.bar(expenseItems, expenseAmounts)
plt.show()
elif option == "a":
t = PrettyTable()
t.add_column("expenseItems",expenseItems)
t.add_column("expenseAmounts",expenseAmounts)
print(t)
else:
print("Invalid option - allowed only (a / b / c")
def main():
while True:
choice = menu()
if choice == '1':
inputExpenseNames()
elif choice == '2':
inputExpenseAmounts(expenseItems)
elif choice == '3':
displayExpenseReport(expenseItems, expenseAmounts)
elif choice == '4':
break
else:
print('Invalid selection. Please re-enter.')
expenseItems = inputExpenseNames()
main()
The error is telling you that you used a variable (expenseItems) that hadn't been defined yet.
What you probably want to do is initialize those variables to empty lists, and then store the results of calling your earlier menu functions so you can pass them to the later functions.
def main():
expenseItems = []
expenseAmounts = []
while True:
choice = menu()
if choice == '1':
expenseItems = inputExpenseNames()
elif choice == '2':
expenseAmounts = inputExpenseAmounts(expenseItems)
elif choice == '3':
displayExpenseReport(expenseItems, expenseAmounts)
elif choice == '4':
break
else:
print('Invalid selection. Please re-enter.')
I'll note that you may want to rethink the idea of having a menu here, since the user always must go through the items in the exact order they're listed. It would be simpler to just automatically go through the three steps in order.

AttributeError: partially initialized module 'calculator' has no attribute 'select' (most likely due to a circular import)

I Am making a small project so i can learn python better, the project has 4 files (i could do this in one but well), 1 as main, 1 as the tool 1, the other as the tool 2 and the other as the tool 3.
i must import the main in the other 3 and the other 3 on the main, this creates a circular import. i cant find how to fix this. any help appreciated
Code:
main.py
import calculator
import texteditor
import textchecker
def start():
print("Operations:")
print("1) Calculator")
print("2) Text Editor")
print("3) Text Checker")
choice1 = input("Select operation: ")
if choice1 == "1":
calculator.select()
elif choice1 == "2":
texteditor.texthub()
elif choice1 == "3":
textchecker.textchub
start()
calculator.py
import main
def select():
while True:
print("Type the number of the operation you want in 'Select a calculation: '")
print("Calculations:")
print("1) Add")
print("2) Subtract")
print("3) Multiply")
print("4) Divide")
print("5) Back To Hub")
global calcinput
calcinput = input("Select a calculation: ")
if calcinput == "1":
global num1
global num2
num1 = int(input("First Number: "))
num2 = int(input("Second Number: "))
elif calcinput == "2":
num1 = int(input("First Number: "))
num2 = int(input("Second Number: "))
elif calcinput == "3":
num1 = int(input("First Number: "))
num2 = int(input("Second Number: "))
elif calcinput == "4":
num1 = int(input("First Number: "))
num2 = int(input("Second Number: "))
elif calcinput == "5":
main.start()
cont = input("Would you like to continue (Yes/No): ")
if cont == "Yes":
continue
elif cont == "No":
main.start()
else:
input("Invalid input. Try again (Yes/No): ")
if calcinput == "1":
print(num1 + num2)
elif calcinput == "2":
print(num1 - num2)
elif calcinput == "3":
print(num1 * num2)
elif calcinput == "4":
print(num1 / num2)
else:
print("Invalid Input!")
textchecker.py
import main
def textchub():
while True:
print("Text Checkers:")
print("1) LowerCase")
print("2) UpperCase")
print("3) Alphabetical")
print("4) Numerical")
print("5) AlNum (Alphabetical/Numerical")
print("6) Back to hub")
ci = input("Choose a checker (Number): ")
if ci == "1" and "2" and "3" and "4" and "5":
cia = input("Paste Text: ")
elif ci == "6":
main.start()
if ci == "1":
if cia.islower() == False:
print("Your text is not lowercase.")
elif cia.islower() == True:
print("Your text is lowercase.")
elif ci == "2":
if cia.isupper() == False:
print("Your text is not uppercase")
if cia.isupper() == True:
print("Your text is uppercase.")
elif ci == "3":
if cia.isalpha() == False:
print("Your text is not only alphabetical")
if cia.isalpha() == True:
print("Your text is only alphabetical.")
elif ci == "4":
if cia.isnumeric() == False:
print("Your text is not only numeric")
if cia.isnumeric() == True:
print("Your text is only numeric.")
elif ci == "5":
if cia.isalnum() == False:
print("Your text is not only AlphabeticalNumerical")
if cia.isalnum() == True:
print("Your text is only AlphabeticalNumerical.")
tcc = input("Would you like to continue Yes/No? ")
if tcc == "Yes":
continue
elif tcc == "No":
main.start
texteditor.py
import main
def texthub():
while True:
print("Editors:")
print("1) UpperCase Text (Every letter will be uppercase)")
print("2) LowerCase Text (Every letter will be lowercase)")
print("3) UpperCase Starting Letter (Every starting letter of every word will be uppercase)")
print("4) Back To Hub")
te = input("Select editor 1, 2, 3 or 4: ")
if te == "1":
t1 = str(input("Paste Text: "))
elif te == "2":
t1 = str(input("Paste Text: "))
elif te == "3":
t1 = str(input("Paste Text: "))
elif te == "4":
main.start()
else:
print("Invalid Input")
if te == "1":
print()
print("Here Is Your Text In UpperCase: " + t1.upper())
elif te == "2":
print()
print("Here Is Your Text In LowerCase: " + t1.lower())
elif te == "3":
print()
print("Here Is Your Text In Title Form: " + t1.title())
if te == "1":
tec = input("Would you like to edit another text Yes/No? ")
if te == "2":
tec = input("Would you like to edit another text Yes/No? ")
if te == "3":
tec = input("Would you like to edit another text Yes/No? ")
if tec == "Yes":
continue
elif tec == "No":
main.start()
error/traceback:
Traceback (most recent call last):
File "f:\Coding\Microsoft VS Code\CODES\Projects\Multi Tool\main.py", line 1, in <module>
import calculator
File "f:\Coding\Microsoft VS Code\CODES\Projects\Multi Tool\calculator.py", line 1, in <module>
import main
File "f:\Coding\Microsoft VS Code\CODES\Projects\Multi Tool\main.py", line 18, in <module>
start()
File "f:\Coding\Microsoft VS Code\CODES\Projects\Multi Tool\main.py", line 12, in start
calculator.select()
AttributeError: partially initialized module 'calculator' has no attribute 'select' (most likely due to a circular import)
Your code is almost right. __name__ is your friend.
According to the Official Python3 Documentation, there exist a couple of "Built-in relevant read-only attributes".
You will notice that if you make a small modification to main.py it will work fine (see below).
import calculator
import texteditor
import textchecker
def start():
print("Operations:")
print("1) Calculator")
print("2) Text Editor")
print("3) Text Checker")
choice1 = input("Select operation: ")
if choice1 == "1":
calculator.select()
elif choice1 == "2":
texteditor.texthub()
elif choice1 == "3":
textchecker.textchub
if __name__=='__main__':
# protect the "start()" with a __name__==__main__ guard
start()
To keep it simple just remember: when importing modules, __name__ is different from ___main___ so those lines won't be executed.
The only time __name__==__main__ yields true is when you run it yourself from command-line, i.e. >python3 main.py.
EDIT: as mentioned in another answer, this does not fix the circular import issue. This is a valid observation in terms of architecture, but please remember that Python is a very flexible and interpreted language, and there is nothing formally preventing you to import from main.py. Just note the power of discerning "who is importing you" by the built-in attributes (__name__), and keep acquiring the best-practices in design outside the scope of this question.
You are importing main from calculator.py, textchecker.py and texteditor.py. While also importing those in main. So, when it tries to resolve this:
in main.py:
--> load in calculator
in calculator.py
--> load in main
in main.py:
--> load in calculator
... you see what goes wrong.
there are 2 solutions to you problem:
in my opinion the best solution
in all the other files besides main replace main.start() with return None. I think your program will continue working as you intended. And remove the imports from those files.
If you want to keep you program running exaclty as it does now(not really good practice)
switch the order of the definition of imports and the function
def start(): ...
# ecapsulate everything in a while here, and add an else: return None
# every other input when choosing will break the loop and stop the program
import ...
then in the rest of the files:
from main import start
But I don't think this is ideal since you will nest function frames and thats memory expensive.
PS: also look add the other answer and add the __name__ == "__main__"
general advise: It's generally not a good idea to import from main. Try to design the calculator, ... keeping in mind you don't know how it's going to be used, just the bare bones functionality(in this case prompt some questions for calculations for example). then in main you can call those functions without them relying on the use case. Say you want a second interface to calculator, .. What are you gonna do then?

Python - Never Ending While Loops caused by a Definition

I'm currently making a main menu for my scoring system that will take the user to different parts of code by using while loops as a simple form of validation but it causes a never ending while loops because some of my definition also have while loops as well. Here's what I've done
def menu():
print("""\n Main Menu \n
1) Join the Event as a Team
2) Join the Event by Yourself
3) Score Screen""")
menuchoice_option = ["1","2","3"]
menuchoice = ""
while menuchoice not in menuchoice_option:
menuchoice = input("Please enter your choice here:")
if menuchoice == "1":
team_menu()
menuchoice = True
elif menuchoice == "2":
individual()
menuchoice = True
elif menuchoice == "3":
#scorescreen()
menuchoice = True
else:
menuchoice = False
print("Please enter a value between 1-3")
menuchoice = input("Please enter your choice here:")
Here's my other functions that the menu def causes to do an infinite whille loops
def team_menu():
global teamS
team_player = ""
while team_player != "":
team_player = input("What is your name:")
print("""\n Available Teams \n
1) Team Ahab
2) Team Ishmael
\n 3) Go back to Main Menu\n""")
team_choice = ""
team_choice_option = ["1","2","3"] # all valid choices on team menu
while team_choice not in team_choice_option:
team_choice = input("Enter your choice here:")
if team_choice == "1":
teamS["Team 1"]["Team Ahab"].append(team_player)
print(teamS["Team 1"])
print("Thank You for Joining Team Ahab")
team_choice = True
elif team_choice == "2":
teamS["Team "+ team_choice]["Teeam Ishmael"].append(team_player)
print(teamS["Team 2"])
print("\nThank You for Joining Team Miller\n")
team_choice = False
elif team_choice == "3":
menu()
team_choice = True
else:
print("Enter a value between 1-3")
team_choice = False
My ideal output would be for it stop causing infinite while loops from different defs in my code. I'm a beginner so please execuse me
Old:
Well... True will never be one of your menuchoice_option, they are 1,2,3.
Make menuchoice="1" (instead of True), for example, if the user select "1".
Edit:
Try to simplify your code: ideally, data should be atomic, and code should work around the data to extract and act as best/smart as possible. And use a better indentation (helps seeing the blocks).
Something like the following would be much, much better to maintain/develop:
def menu():
options = {
1: "Join the Event as a Team",
2: "Join the Event by Yourself",
3: "Score Screen"
}
funcs = {
1: team_menu,
2: individual,
3: scorescreen
}
print("\n Main Menu \n")
for k,v in options.items():
print(f"{k}) {v}")
choice = None
while choice not in options:
# notice that if a value invalid for "int()" casting,
# the code will blow. Wrap this with try/except to avoid it.
choice = int(input("Please enter your choice here:"))
# By now, you know a valid option was chosen.
# Let's use to select the corresponding function from "funcs" dict
funcs[choice]()
I did not test it. But looks like working.
How about using some recursion for the menu, I share my idea:
options = """
Main Menu
1) Join the Event as a Team
2) Join the Event by Yourself
3) Score Screen
4) Exit
>>> """
def menu(menuchoice):
if menuchoice == "1":
team_menu()
elif menuchoice == "2":
individual()
elif menuchoice == "3":
#scorescreen()
pass
elif menuchoice == "4":
exit()
else:
print("Please enter a value between 1-5")
decision = str(input(">>> "))
menu(decision)
if __name__ == "__main__":
decision = str(input(options))
menu(decision)
I hope I give you an idea.

Part of my Python Code is not functioning, but all other parts are

I have a code in Python that I recently created for a Maths Assignment, but part of it is not working.
So it asks the user to select a choice, but when I tested it, all other options (which I took out) worked for me, but when I entered "4", it wouldn't work. Instead, it just reprinted everything and asked for my choice again.
FYI: I have taken out the other options, because they aren't needed here.
Does anybody have a solution though? Because whatever I do, it doesn't seem to function or work.
Here's the part of my code that has the problem:
#This part greets the user, and lets the user know that the application has started
print("Hello there!")
#This starts off the loop, but this variable may be changed later on
cont = "yes"
#This is the actual loop
while cont == "yes" or cont == "Yes" or cont == "YES":
print("Choose an option below:")
#This shows the options
print("1) Calculate the value of different product sizes")
print("2) Calculate the sale price")
print("3) Calculate the discount")
print("4) Create a shopping list")
print("5) Create a receipt that shows costs")
print("6) Exit")
#This part lets the user choose what they would like to do
option = float(input("Choose an option (1/2/3/4/5/6): "))
#This is what happens if the user chooses Option 4
#This is the "Shopping list" part of the application below
if option == 4:
sl = []
import os,sys,time
try:
f = open("Shopping_List.txt","r")
for line in f:
sl.append(line.strip())
f.close
except:
pass
def mainScreen():
os.system("cls")
print("Just a couple reminders:")
print("Your shopping list contains", len(sl), "items so far.")
print("If items aren't deleted from the list after use, they'll remain there.")
print("Choose an option below:")
print("1) Add an item to the list")
print("2) Delete an item from the list")
print("3) View the list")
print("4) Exit")
asdf = input("Enter your choice here: ")
if len(asdf) > 0:
if choice.lower()[0] == "1":
addScreen
elif choice.lower()[0] == "2":
deleteScreen()
elif choice.lower()[0] == "3":
viewScreen()
elif choice.lower()[0] == "4":
sys.exit()
else:
mainScreen()
else: mainScreen()
def addScreen():
global sl
os.system('cls')
print("Press ENTER if you would like to exit.")
print("Enter the name of the item you would like to add below.")
item = input("Name of item: ")
if len(item) > 0:
sl.append(item)
print("Item has been added.")
saveList()
time.sleep(1)
addScreen()
else:
mainScreen
def viewScreen():
os.system('cls')
for item in sl:
print(item)
print("Press ENTER to exit.")
input()
mainScreen()
def deleteScreen():
global sl
os.system('cls')
count = 0
for item in sl:
print(count, ") - ", item)
count = count + 1
print("Enter the number corresponding to the item you would like to delete.")
chce = ("Number: ")
if len(chce) > 0:
try:
del sl[int(chce)]
print("Item has been deleted.")
saveList()
time.sleep(1)
except:
print("Invalid number.")
time.sleep(1)
deleteScreen()
else:
mainScreen()
def saveList():
f = open("Shopping_List.txt", "w")
for item in sl:
f.write(item + "\n")
f.close()
mainScreen
Thanks in advance.
Here's the solution:
The line at the bottom of my code should be changed from mainScreen to mainScreen(), otherwise it wouldn't do anything. And also, if choice.lower()[0] == "1": addScreen should be if choice.lower()[0] == "1": addScreen(), or otherwise, that part of my code wouldn't function either, which would create further problems.
Credit goes to Keith John Hutchison and MaxiMouse for helping me figure out how to solve my problem, why it didn't work, and for also suggesting improvements to my code.

Categories