I have a program that is supposed to show all classes in the external .txt file when the user presses "V", and is supposed to allow the user to lookup a specific class based off of its course code (EX. user types csce101 and it will print "Introduction to computer concepts"). However, I can't get the V and L functions to work properly. As it sits currently, the V function is only working because I called a break... but after it prints all the classes, it asks the user for a course code when it is not supposed to. That is what the L function is supposed to do. I am unsure on how to call a function inside of an if/elif loop. The function name just comes up as undefined. Is it possible with the way I have the code setup?
Python Code:
while True:
command = input("(V)iew, (L)ookup, or (Q)uit: ")
if command == "v":
break
elif command == "l":
print(f"{code}")
elif command == "q":
print("Goodbye!")
quit()
else:
print("Invalid command")
def getCourses():
courses = {}
with open("assignments/assignment-19/courses.txt") as file:
for line in file:
data = line.split(':')
code = data[0].strip()
className = data[1].strip()
courses[code] = className
return courses
def getDescription(courseList):
code = input("Enter course code: ").strip().lower()
if code in courseList:
print(f"{courseList[code]}")
else:
print(f"Sorry {code} is not in our system")
courseList = getCourses()
for classes in courseList:
print(f"{classes}: {courseList[classes]}")
getDescription(courseList)
.txt file contents
csce101: Introduction to Computer Concepts
csce102: General Applications Programming
csce145: Algorithmic Design 1
csce146: Algorithmic Design 2
csce190: Computing in the Modern World
csce201: Introduction to Computer Security
csce204: Program Design and Development
csce205: Business Applications Programming
Some general observations:
Functions, like any other object, need to be defined before they are
referenced/used. You aren't violating this, but you will be if you
fill in the rest of your while-loop. Ideally, you'll want a main
entry point for your program, so that it's clear in what order things
are being executed, and your functions are guaranteed to be defined
by the time flow-of-execution reaches the lines on which your functions are called.
It would make sense to define one function for each corresponding
command type (except for quit). You were on the right track here.
A couple questionable/redundant instances of f-strings (f"{code}" almost certainly doesn't do what you think it should.)
Prefer snake_case over camelCase when writing Python source code.
Your V command will terminate the loop (and the program)
prematurely. What if the user wants to print all courses, then a
description?
Here are my suggestions incarnate:
def get_courses():
courses = {}
with open("assignments/assignment-19/courses.txt", "r") as file:
for line in file:
data = line.split(":")
code = data[0].strip()
class_name = data[1].strip()
courses[code] = class_name
return courses
def display_courses(courses):
for key, value in courses.items():
print(f"{key}: {value}")
def display_description(courses):
code = input("Enter course code: ").strip().lower()
if code in courses:
print(courses[code])
else:
print(f"Sorry, \"{code}\" is not in our system.")
def main():
courses = get_courses()
while True:
command = input("(V)iew, (L)ookup or (Q)uit: ").lower()
if command == "v":
display_courses(courses)
elif command == "l":
display_description(courses)
elif commany == "q":
print("Goodbye!")
break
else:
print("Invalid command.")
# 'main' ends here
main()
Related
No matter how many times I google variations of my question, I cannot seem to find a solution. I am a beginner programmer, trying to build a game that randomly generates events as you progress through the stages. The problem I am running into are return statements, and passing the values between different modules. Each method for each file are inside of classes. They are all static methods, and calling these methods is not my problem. It is transferring the value of the variables. I'm not sure where I am going wrong, whether it is how I am structuring it, or if I just don't understand how these return statements work.
This is the first File I am starting from. Print statements will be filled out after everything functions properly.
def story():
print("---Intro Story Text here--- ... we will need your name, Traveler. What might it be?")
user_prompt = Introduction.PlayerIntroduction
name = user_prompt.player_info(1)
print(f"Welcome {name}!")
print(f"----After name is received, more story... how old might you be, {name}?")
age = user_prompt.player_info(2)
This is the file I am trying to get the values from. File: Introduction, Class: PlayerIntroduction
#staticmethod
def player_info(funct_select):
if funct_select == 1:
name = PlayerIntroduction.get_player_name()
player_name = name
elif funct_select == 2:
age = PlayerIntroduction.get_player_age()
player_age = age
return player_name, player_age
#staticmethod
def get_player_name():
print("\n\n\nWhat is your name?")
players_name = input("Name: ")
while True:
print(f"Your name is {players_name}?")
name_response = input("Yes/No: ")
if name_response == "Yes" or name_response == "yes":
name = "Traveler " + players_name
break
elif name_response == "No" or name_response == "no":
print("Let's fix that.")
PlayerIntroduction.get_player_name()
else:
print("Please respond with 'Yes' or 'No'.")
return name
#staticmethod
def get_player_age():
print("\n\n\nHow old are you?")
age = input("Age: ")
while True:
print(f"Your age is {age}?")
age_response = input("Yes/No: ")
if age_response == "Yes" or age_response == "yes":
break
elif age_response == "No" or age_response == "no":
print("Let's fix that.")
PlayerIntroduction.get_player_age()
else:
print("Please respond with 'Yes' or 'No'.")
return age
I would like to use the values for "name" and "age" throughout multiple modules/multiple methods within my program. But in order to get those values, I need to assign a variable to the function call.. Resulting in prompting the user to re-enter their name/age at later stages in the game. My idea to combat this was in the first method of this module, creating a conditional statement "if 'example' == 1: 'run the name prompt' and elif == 2: run age prompt, thinking the initial run with the arguments defined would run these prompts, store the values into the variables (name, age), and finally pass the values to the new variables that are NOT assigned to the function call (p_name, p_age), avoiding triggering the user prompt over and over. Ultimately, this failed, and as the code sits now I am getting:
UnboundLocalError: local variable 'player_age' referenced before assignment
Why is this? The only instance 'player_age' is called that is reachable at this point is in the return statement, indented in-line with the conditional statement. The code should read (If I understand incorrectly, please explain) from top to bottom, executing in that order. The 'if' condition is met, so it should run that. If I were to define 'player_name' and 'player_age' as null at the top of this method to avoid this error, then every time I would need to reference these values initially entered by the user, they would be re-assigned to 'null', negating everything I am trying to do.
Thank you all for your patience, I tried to explain what I was doing and my thought process the best I could. Any feedback, criticism, and flaws within my code or this post are GREATLY appreciated. Everything helps me become a better programmer!! (:
So I am making a program in which it reads a .txt file and runs different classes; I made it so it opens the file and stores the text in a decision string, Using if decision == "wincode" or "lostcode" I want it to run a specific class like:
class wonToss():
wininput = input("Do you want to choose: ")
def outChoice():
print("no error")
def inChoice():
print("No error")
if wininput == "Indoor":
inChoice()
elif wininput == "Outdoor":
outChoice()
I put the "No error" for testing to see if it works
class lostToss():
def botChoose():
print("Bot is choosing between Indoor and Outdoor.")
print(".")
time.sleep(0.25)
print("..")
time.sleep(0.25)
print("...")
time.sleep(0.25)
print("")
choices = ['Indoor', 'Outdoor']
botting = random.choice(choices)
print(f"And the bot chose: {botting}")
time.sleep(2)
botChoose()
And this is the second class. So now, I want it to check the code and class the specific class.
This is the check code:
f=open("TossDecision.ch", "r")
if f.mode == 'r':
decision = f.read()
if decision == "jhe78r2dbgv67t2yhdb7vgr":
print("")
wonToss()
elif decision == "jhe78rnxshwdn7wgh89u3cn":
print("")
lostToss()
else:
print("Toss Decision changed! Re-run the PlayGame file.")
exit()
But the problem is,
When I run the program it just shows:
Do you want to choose (Indoor) or (Outdoor)?: Indoor
Bot is choosing between Indoor and Outdoor.
.
..
...
And the bot chose: Indoor
It calls both the classes. Currently its set to loss. It still calls wonToss() Can anyone help fix this
Sorry, but you are using classes totally wrong.
Please read on Object-oriented programming.
A class is a blueprint for an object.
In most times, you instantiate an object of the class, and work with it. Like this:
class Mything:
def InChoice(self):
print("No errror indoors")
def OutChoice(self):
print("No error outdoors")
def ask_choice(self):
wininput = input("Do you want to choose: ")
if wininput == "Indoor":
self.InChoice()
elif wininput == "Outdoor":
self.OutChoice()
Then in your program you do:
choice_object=Mything()
choice_object.ask_choice()
What I am trying to do is to make an app so, while the user is using the app he can add an instance for a class.
To be more specific, I am trying to make a rating app for the workers but, I need to make the user to be able to add a worker to the app which I want to be treated as an instance in the backend code which has a class called worker.
and here is the code to understand what I am trying to say more.
class worker:
"""
This class is responsible for any worker been rated.
INPUT: name of rated worker
OUTPUT: the rating
"""
def __init__(self, name):
self.name = name
def rate(self):
rating = input(f"What is your rating for {self.name}")
#open a file and append the rating to it.
rat_stor = open(f"{self.name}rating_storage", "a+")
rat_stor.write(rating + ",")
rat_stor.close()
#open a file and read it.
rat_stor = open(f"{self.name}rating_storage", "r")
rat_stor_read = rat_stor.read()
rat_stor.close()
#I have the all the ratings as a list.
lis_rat = rat_stor_read.split(",")
#going to be used as a filter for non-numerical values
int_lis = []
for i in lis_rat:
#if the string can be converted to an integer then, add it to int_lis
try:
int_lis.append(int(i))
except:
pass
rates_sum = sum(int_lis)
rates_amount = len(int_lis)
self.result = rates_sum / rates_amount
def __str__(self):
return self.name + str(round(self.result,1))
You need to design a user interface for your program - if you want a windowed application then you could either use tkinter (built in to python) or you could find a package that does the job you want (installable using pip). Or you could make a web app with a package such as django. If this isn't a commercial application then the simplest option is to just make a command line application (using print and input)
For a windowed/graphical application: you need to consider what process the user should go through to add a worker/submit a rating. Presumably some data needs to be inputted (their name, etc.) The package you choose will allow you to build an interface for this.
Edit:
A command line app that illustrates how you might make a menu system, Allows you to create/rate workers. Error handling is very limited and workers are not saved to disk so they will be lost when the program is closed. I recommend looking into a module called pickle for saving data to disk - much more powerful that manually writing to a file. This example is written for Python version >3. For Python 2 you will need to use raw_input() instead of input
# --- file name: manageworkers.py ---
class Worker: #I'm using this in place of your class for simplicity
def __init__(self):
self.name = ""
self.ratings = []
def rate(self):
#Normally code that takes user input should be with the rest of the code for the menu. Have put this here to stay consistent with your code.
print("What is your rating for {}?".format(self.name))
self.ratings.append(input(">"))
print("Rating saved!")
workers = []
def mainMenu():
while True:
print("Please select an option:")
print("\t1) Add a worker")
print("\t2) Rate a worker")
print("\t3) View worker ratings")
print("\t4) Exit")
while True:
choice = int(input(">")) #Will break if you don't enter a valid number
if choice == 1:
addWorker()
break
elif choice == 2:
rateWorker()
break
elif choice == 3:
viewRatings()
break
elif choice == 4:
return
else:
print("Invalid selection - please try again")
def addWorker():
global workers
newWorker = Worker() #This is where the instance is created
print("What is the name of the worker?")
newWorker.name = input(">")
workers.append(newWorker) #Keep the worker somewhere so we can use it later
print("Worker Saved!")
def chooseWorker():
global workers
if len(workers) == 0:
print("There are no workers.")
return
#Let's print a menu
print("Please select a worker:")
for n, w in enumerate(workers):
print("\t{}) {}".format(n+1, w.name)) #Add one to n so numbering starts at 1
#Now we need to work out what the user entered
while True:
selection = int(input(">")) - 1 #Take the one away again so array indexing starts at 0. Will break if you don't enter a number.
if selection >= 0 and selection < len(workers):
return workers[selection]
break
else:
print("Invalid selection, please try again.")
def rateWorker():
workerToRate = chooseWorker()
if workerToRate != None:
workerToRate.rate()
def viewRatings():
workerToView = chooseWorker()
if workerToView != None:
if len(workerToView.ratings) == 0:
print("Worker has no ratings.")
else:
print("Ratings for {}:".format(workerToView.name))
for rating in workerToView.ratings:
print("\t{}".format(rating))
if __name__ == "__main__":
mainMenu()
I am extremely new to Python, and to programming in general, so I decided to write some basic code to help me learn the ins and outs of it. I decided to try making a database editor, and have developed the following code:
name = []
rank = []
age = []
cmd = input("Please enter a command: ")
def recall(item): #Prints all of the information for an individual when given his/her name
if item in name:
index = name.index(item) #Finds the position of the given name
print(name[index] + ", " + rank[index] + ", " + age[index]) #prints the element of every list with the position of the name used as input
else:
print("Invalid input. Please enter a valid input.")
def operation(cmd):
while cmd != "end":
if cmd == "recall":
print(name)
item = input("Please enter an input: ")
recall(item)
elif cmd == "add":
new_name = input("Please enter a new name: ")
name.append(new_name)
new_rank = input("Please enter a new rank: ")
rank.append(new_rank)
new_age = input("Please input new age: ")
age.append(new_age)
recall(new_name)
else:
print("Please input a valid command.")
else:
input("Press enter to quit.")
operation(cmd)
I want to be able to call operation(cmd), and from it be able to call as many functions/perform as many actions as I want. Unfortunately, it just infinitely prints one of the outcomes instead of letting me put in multiple commands.
How can I change this function so that I can call operation(cmd) once, and call the other functions repeatedly? Or is there a better way to go about doing this? Please keep in mind I am a beginner and just trying to learn, not a developer.
Take a look at your code:
while cmd != "end":
if cmd == "recall":
If you call operation with anything than "end", "recall" or "add", the condition within while is True, the next if is also True, but the subsequent ifs are false. Therefore, the function executes the following block
else:
print("Please input a valid command.")
and the while loop continues to its next lap. Since cmd hasn't changed, the same process continues over and over again.
You have not put anything in your code to show where operator_1, operator_2, and operator_3 come from, though you have hinted that operator_3 comes from the commandline.
You need to have some code to get the next value for "operator_3". This might be from a list of parameters to function_3, in which case you would get:
def function_3(operator_3):
for loopvariable in operator_3:
if loopvariable == some_value_1:
#(and so forth, then:)
function_3(["this","that","something","something else"])
Or, you might get it from input (by default, the keyboard):
def function_3():
read_from_keyboard=raw_input("First command:")
while (read_from_keyboard != "end"):
if read_from_keyboard == some_value_1:
#(and so forth, then at the end of your while loop, read the next line)
read_from_keyboard = raw_input("Next command:")
The problem is you only check operator_3 once in function_3, the second time you ask the user for an operator, you don't store its value, which is why its only running with one condition.
def function_3(operator_3):
while operator_3 != "end":
if operator_3 == some_value_1
function_1(operator_1)
elif operator_3 == some_value_2
function_2
else:
print("Enter valid operator.") # Here, the value of the input is lost
The logic you are trying to implement is the following:
Ask the user for some input.
Call function_3 with this input.
If the input is not end, run either function_1 or function_2.
Start again from step 1
However, you are missing #4 above, where you are trying to restart the loop again.
To fix this, make sure you store the value entered by the user when you prompt them for an operator. To do that, use the input function if you are using Python3, or raw_input if you are using Python2. These functions prompt the user for some input and then return that input to your program:
def function_3(operator_3):
while operator_3 != 'end':
if operator_3 == some_value_1:
function_1(operator_3)
elif operator_3 == some_value_2:
function_2(operator_3)
else:
operator_3 = input('Enter valid operator: ')
operator_3 = input('Enter operator or "end" to quit: ')
looks like you are trying to get input from the user, but you never implemented it in function_3...
def function_3(from_user):
while (from_user != "end"):
from_user = raw_input("enter a command: ")
if from_user == some_value_1:
# etc...
I'm teaching myself Python and writing a simple GPA calculator. I have very little programming experience prior other than a college Java course, so bear with my code.
The premise is, the code will ask if you want to add a course to the list. If you do, it runs a function asking you the class name. Every time you add a class it'll ask if you want to add another. If you don't, it'll spit out a list of the classes you've added and then ask you to enter in the grades. I didn't get the grading part done yet. I don't think that will be too hard.
The problem is you can add a bunch of classes and it will only spit out the last one you entered. I'm assuming the issue is in askAgain(): classList = addClasses() because it keeps overwriting, but I'm not sure how to avoid a global variable (since they're bad?) and still keep this from overwriting itself. I seem to draw a blank when trying to figure out how to call something once to intialize it and not run it again. I've also read that conditional variables are bad, so I'm not sure what's best practice here. thanks
def main():
askAgain()
return 0
def askAgain():
while True:
addOrNot = raw_input("Add a class? [y/n]: ")
if addOrNot == "Y" or addOrNot == "y":
classList = addClasses() #This is probably where my issue is.
else:
try:
editClassGradeSelection = mainMenu(classList)
addGrades(editClassGradeSelection, classList)
except:
print("Hey you didn't add any classes yet.")
def addClasses():
try:
if classList in locals():
print("debug msg - classList exists")
except:
classList = []
classList.append(raw_input("Add class to the list: "))
return classList
def mainMenu(classList):
print("Here are the classes you've added: ")
counter = 0
for classes in classList:
print((str(counter+1)) + ". " + (str(classList[counter])) + "\n")
counter = counter + 1
while True:
editGrade = raw_input("Enter the number for the class grade to edit: ")
if int(editGrade) > len(classList) or int(editGrade) < 1:
print("Enter a proper number in the range listed.")
else:
break
return editGrade
def addGrades(editClassGradeSelection, classList):
print("debug stuff for now: ")
print((str(editClassGradeSelection)))
print((str(classList[:])))
if __name__ == '__main__':
main()
Although this snippet makes sure classlist is defined:
try:
if classList in locals():
print("debug msg - classList exists")
except:
classList = []
classlist is a local variable, hence everytime you run that function, classlist will be [], which probably explains why you can't ever display more than one. The classlist you assign it to gets reassigned to the one element of classlist (addClasses scope) every time this line is called:
classList = addClasses() #This is probably where my issue is.