I got trouble in using self-defining functions with Python - python

I wrote a simple program about User sign_up & log_in System with Python.I used many self-defining functions to make codes elegant. Here is the 'choose_page' function:
def choose_page():
print('Welcome to the code system!')
print('****************************\n')
print('there are the three options:\n'
'1.sign up\n'
'2.log in\n'
'3.quit')
print('****************************\n')
option = eval(input('Please input your option:'))
return option
And here is 'sign_up' function:
def sign_up():
global customer
# global option
# global option2
..................
..................(many codes)
option2 = eval(input('Now you can log in the main page by inputting 2 or 0 to return the sign_page: '))
return option2
I also wrote 'log_in' and 'quit' self-defining functions,then I can company them as I want like this(this step without 'quit' function as it doesn't matter now):
if choose_page() == 1:
sign_up()
if sign_up() == 0:
choose_page()
elif sign_up() == 2:
log_in()
elif choose_page() == 2:
log_in()
I run it but got trouble seems like logic error:
When I got in 'choose_page' and input 1,it run into 'sign_up',at the end of the 'sign_up',I input either 2 or 0 it still run into the 'sign_up' again and again without stopping.
Is there any logic error when I company these self-defining functions?
Thanks for help in advance.

Every time you write sign_up() it's going to call it and run through the function. Python isn't smart. It doesn't go, "We've already run sign_up() before. I remember the answer. No need to run it again!" It does exactly what you tell it. If you write sign_up(), it calls sign_up().
To avoid the repeated prompts you need to save its result to a variable and only call the function a single time.
if choose_page() == 1:
sign_up_answer = sign_up()
if sign_up_answer == 0:
choose_page()
elif sign_up_answer == 2:
log_in()
Repeat that same idea for any of the other functions that have the same problem.

Related

Creating a Python game, working with returns in-between multiple modules

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!! (:

NameError: name 'furnish' is not defined Python

def getType():
inp=int(input("\t<<<<<APARTMENT RENTAL PROGRAM>>>>>\n1 studio\n2 One-Bedroom\n3 Two-Bedroom\n4 Exit\nEnter Your Choice ::"))
while(inp>4 or inp<0):
print("Enter Valid Choice!!")
inp=int(input("\t<<<<<APARTMENT RENTAL PROGRAM>>>>>\n1 studio\n2 One-Bedroom\n3 Two-Bedroom\n4 Exit\nEnter Your Choice ::"))
if(inp==4):
return 4,0
furnished=input("Do you want the apartment furnished(Y/N)?")
valid=['y','n','Y','N']
while(furnished not in valid):
print("Enter Valid Choice!!")
furnished = input("Do you want the apartment furnished(Y/N)?")
if(furnished == 'Y' or furnished=='y'):
return inp,1
return inp,0
def determineRent(kind,furnish):
rents=[[400,600,750],[500,750,900],[600,925,1025]]
return rents[kind-1][0],rents[kind-1][furnish+1]
def displayRent(kind,furnish,rent,deposit):
if(kind==1):
print("\tStudio")
elif (kind == 2):
print("\tOne-Bedroom")
elif(kind==3):
print("\tTwo-Bedroom")
**if (furnish == 1):
print("\tFurnished")**
else:
print("\tUnfurnished")
print("\tDeposit : $",deposit)
print("\tRent : $",rent)
I am trying to get rid of my syntax issues and I cannot get my statement to work (bolded) I included the entire code for reference. I tried redefining furnish and changing it to furnished to no avail.
Code inside function definitions (indented under a def statement) is not executed until you call those functions, so will not cause NameErrors when running the program. I'm not sure if this is your intention, but based on the way you have your code indented above, the only code that is being executed is the final if statement and 2 print statements. This should make it clearer:
def getType():
*** definition of getType function ***
def determineRent(kind,furnish):
*** definition of determineRent function ***
def displayRent(kind,furnish,rent,deposit):
*** Definition of displayRent function ***
if (furnish == 1):
print("\tFurnished")
else:
print("\tUnfurnished")
print("\tDeposit : $",deposit)
print("\tRent : $",rent)
Since you never call the getType, determineRent, or displayRent functions, the interpreter just passes through storing those in memory without attempting to actually execute the code. So the first line it actually attempts to execute is:
if (furnish == 1):
But you haven't defined a variable called furnish at this point. That's why you get the NameError. If you write furnish = 1 above this line you'll see that it works (but next you get NameError for deposit instead).
while(furnished not in valid):
print("Enter Valid Choice!!")
That looks like an infinite loop to me :)
Assuming that these are functions called from another module, and that the code erroring out was suposed to be inside the displayRent function, your problem is indentation.
Python has an indentation based syntax, which means that your spaces/tabs at the beginning of the line matter a lot. In this case you have none on your line if (furnish == 1): and on the next lines, which means that Python will understand that they should be considered at the global level of that module. If you want it to be within the displayRent function you need to indent correctly, i.e. add leading tab/spaces to match the rest of the function code. Like this:
def getType():
inp=int(input("\t<<<<<APARTMENT RENTAL PROGRAM>>>>>\n1 studio\n2 One-Bedroom\n3 Two-Bedroom\n4 Exit\nEnter Your Choice ::"))
while(inp>4 or inp<0):
print("Enter Valid Choice!!")
inp=int(input("\t<<<<<APARTMENT RENTAL PROGRAM>>>>>\n1 studio\n2 One-Bedroom\n3 Two-Bedroom\n4 Exit\nEnter Your Choice ::"))
if(inp==4):
return 4,0
furnished=input("Do you want the apartment furnished(Y/N)?")
valid=['y','n','Y','N']
while(furnished not in valid):
print("Enter Valid Choice!!")
furnished = input("Do you want the apartment furnished(Y/N)?")
if(furnished == 'Y' or furnished=='y'):
return inp,1
return inp,0
def determineRent(kind,furnish):
rents=[[400,600,750],[500,750,900],[600,925,1025]]
return rents[kind-1][0],rents[kind-1][furnish+1]
def displayRent(kind,furnish,rent,deposit):
if(kind==1):
print("\tStudio")
elif (kind == 2):
print("\tOne-Bedroom")
elif(kind==3):
print("\tTwo-Bedroom")
if (furnish == 1):
print("\tFurnished")
else:
print("\tUnfurnished")
print("\tDeposit : $",deposit)
print("\tRent : $",rent)
Documentation for reference and better understanding: Python Docs - Indentation

Running a function inside of an if statement

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()

I cant find whats causing my program to stop working after i but everything into separate functions

So I originally had everything outside functions. Meaning there was no 'def' or 'return' anywhere. and all the displays came out fine.
But now that I'm trying to use Main function as a switch to call other functions. my output disappeared, and when i entered '1' then '1' would just be repeated back at me. I am confused how where I made my mistake.
Then I am trying to return to my main function after I enter 'a' but I do not know how to do that.
Can anyone help me fix this?
~Im using Thonny Python IDE on a raspberry pi if that helps.
Here is my code:
#
import sys, random
def main():
slct= input()
if slct==1:
set1()
elif slct==2:
set2()
elif slct ==3:
set3()
return
def set1():
n1= random.randint(0,9)
pw1= random.randint(1,3)
print(n1)
if pw1==1:
print('one')
elif pw1:
print('ten')
else:
print('hundred')
return
def set2():
n2= random.randint(0,9)
pw2= random.randint(1,3)
print(n2)
if pw2==1:
print('thousand')
elif pw2:
print('ten thousand')
else:
print('hundred thousand')
return
def set3():
n3= random.randint(0,9)
pw3= random.randint(1,3)
print(n3)
if pw3==1:
print('one million')
elif pw3:
print('ten million')
else:
print('hundred million')
return
you need call main().
add main() at the end of your file.
Also you don't need to add return at the end of every function unless you want to return any value e.g. return "passed"
I don't know what you are doing with this code but as set1(), set2() and set3() are same,following code is also similar to what you have:
import sys, random
def main():
n1= random.randint(0,9)
pw1= random.randint(1,3)
print(n1)
if pw1==1:
print('one')
elif pw1:
print('ten')
else:
print('hundred')
return
main()

I want to apply unit tests to simple numeric playback code

I recently started programming with Python for the first time. I have been told that I can not access the essence of unit testing for this code. I tried to practice by listening to the importance of unit testing and Python unit testing.
The code is shown below.
# UpDown.py
import random
import unittest
servicenumber = 0
exp = 0
## Game play screen
def start_screen():
global servicenumber
exe = """
==============================
1. Up/Down Game Start
2. Exp check
3. exit
==============================
Please enter your desired service number."""
print(exe)
servicenumber = input()
if servicenumber == 1:
start_game()
elif servicenumber == 2:
check_exp()
elif servicenumber == 3:
game_exit()
else:
print "Please enter one of 1, 2, or 3."
## Up/Down This is the part of the game.
def start_game():
re = 1
global servicenumber
global exp
if servicenumber == 1:
while re != 0:
notice = """
==============================
Randomly generated values ​​are from 1 to 100.
Players should enter a number between 1 and 100.
If you win, you gain 2 exp, and if you lose, it decreases by 1.
Please enter 0 to finish.
==============================\n"""
print(notice)
var = input('input : ')
if var > 100:
print 'Please enter a value between 1 and 100.'
continue
elif var < 0:
print 'Please enter a value between 1 and 100.'
continue
elif var == 0:
re = 0
else:
print ''
randvalue = random.randrange(1,101)
if var > randvalue:
print 'Up'
exp = exp + 2
print "exp+2"
print "Your experience ",exp
print "Randomly generated values ",randvalue
continue
elif var < randvalue:
print 'Down'
exp = exp-1
print 'Decreasing story ~~'
continue
elif var == randvalue:
print 'The story of being tapped ~~'
continue
else:
print "Randomly generated values ",randvalue
continue
start_screen()
def check_exp():
global servicenumber
if servicenumber == 2:
print "Experience: ",exp
start_screen()
## (exit)
def game_exit():
global servicenumber
if servicenumber == 3:
print 'Exit'
exit()
if __name__ == "__main__":
start_screen()
else:
print "Imported. Start unit testing.\n"
And the code I tried to practice
I think it is pointless.
import unittest
import UpDownGame
class testing(unittest.TestCase):
def test_start(self):
self.assertTrue(UpDownGame.start_screen)
def test_game(self):
self.assertTrue(UpDownGame.start_game)
def test_chkexp(self):
self.assertTrue(UpDownGame.check_exp)
def test_exit(self):
self.assertTrue(UpDownGame.game_exit)
def initialize():
return testing
if __name__ == "__main__":
testsuite = (unittest.makeSuite(testing))
unittest.TextTestRunner(verbosity=2).run(testsuite)
So I want advice on unit testing.
I would really appreciate it if you let me know how to apply unit tests to this code.
Also, let me know if you think I have the basic knowledge I need.
Thank you.
The problem is that you're trying to write the tests when you've already written the code, and you've started with inherently hard to test code. If you wrote the tests before each part of code they are intended to test then you would write the code quite differently.
So, ignoring your code entirely, you want a 'start_screen' function that will print a prompt, read some input, and call a function based on that input. You don't want to hard-wire the functions that get called (because that makes it harder to test), so you might change the function so it takes a dictionary of actions and then you can pass in test actions in place of the ones the real code will run. You also don't want it reading from input() so again you might make that customisable. Writing output with print is also a bad idea for testing, as you'll want to catch the output if you need to make any assertions about it but we'll ignore that for now.
So, change def start_screen() to:
DEFAULT_ACTIONS = { 1: start_game, 2: check_exp, 3: game_exit }
def start_screen(actions=DEFAULT_ACTIONS, input=input):
pass
and write a test:
def test_start_input_1_calls_action_1(self):
calls = []
dummy_actions = { 1: lambda: calls.append('action1') }
def dummy_input():
calls.append('input')
return 1
start_screen(actions=dummy_actions, input=dummy_input)
assert calls == ['input', 'action1']
next you verify that the test compiles and runs and fails with an assertion error. If it fails for any other reason you fix the test.
Only then, you change start_screen so that the test now passes.
Then you can add other tests. A good next test would be one where the 'input' function returns 4 the first time it is called and then a 1:
def test_start_input_4_prompts_again(self):
calls = []
inputs = [1, 4]
dummy_actions = { 1: lambda: calls.append('action1') }
def dummy_input():
calls.append('input')
return inputs.pop(0)
start_screen(actions=dummy_actions, input=dummy_input)
assert calls == ['input', 'input', 'action1']
Now you verify that you get an assertion error, then you modify the code so that the test passes. Now the most important step: you look at the two tests and see that they are almost identical so you remove the duplication to another function and modify the tests so they look something like this:
def test_start_input_1_calls_action_1(self):
self.start_helper([1], ['input', 'action1'])
def test_start_input_4_prompts_again(self):
self.start_helper([4, 1], ['input', 'input', 'action1'])
def start_helper(self, inputs, expected_calls):
... add code here ...
then go on to write tests for the other functions. You will want to lose the global variable: tested functions need to be clean and not depend on variables set outside. Also that recursive call it probably the wrong thing to do, you might want to consider making start_screen have a loop and in that case the tests we just wrote will have to be updated for that.
At every step the fact that you have already written the test is going to influence how you think about the code.

Categories

Resources