I was working on a lab assignment and I've been struggling with an error for days. I coded return as well in my function and it keeps saying there's a NameError: and I didn't define it.
Here's the code I'm working on and it's all messed up since I'm not done. But I'd love to know what did I messed up and how can I fix the name error. Thanks!
import random
def main():
instructions = display_instructions("instructions.txt")
#display instructions
display_instructions(instructions)
list_of_words = ['apple', 'banana', 'watermelon', 'kiwi', 'pineapple',
'mango']
correct_word=random.choice(list_of_words)
answer = list(correct_word)
puzzle = []
puzzle.extend(answer)
display_puzzle_string(puzzle)
play_game(puzzle, answer)
display_result(is_win, answer)
input('Press enter to end the game.')
def display_instructions(filename):
instruction_file=open("instructions.txt","r")
file_contents=instruction_file.read()
instruction_file.close()
print(file_contents)
def display_puzzle_string(puzzle):
for i in range(len(puzzle)):
puzzle[i] = '_'
print('The answer so far is '+" ".join(puzzle))
def play_game(puzzle, answer):
num_guesses = 4
while num_guesses > 0:
get_guess(num_guesses)
update_puzzle_string(puzzle, answer, guess)
display_puzzle_string(puzzle)
is_word_found(puzzle)
def get_guess(num_guesses):
guess=input('Guess a letter '+'('+str(num_guesses)+' guesses remaining):')
return guess
def update_puzzle_string(puzzle, answer, guess):
for i in range(len(answer)):
if guess.lower() == answer[i]:
puzzle[i] = guess.lower()
num_guesses += 1
return puzzle
def is_word_found(puzzle):
if puzzle == answer:
return is_win
def display_result(is_win, answer):
if is_win:
print('Good job! You found the word '+correct_word+'!')
else:
print('Not quite, the correct word was '+correct_word+
'. Better luck next time')
main()
In the function play_game, you have the line get_guess(num_guesses) which returns the variable guess. However, you are not assigning the guess to a variable in the function. You can fix this by changing that line to guess = get_guess(num_guesses). The error tells you exactly what is wrong. You have not defined the variable guess so far.
Your code has different flaws. The main errors are related to indentation and function scopes. Keep in mind that Python uses indentation to group statements. Use 4 spaces consistently as indentation for grouping statements, e.g. to indent the function body, for-loop body etc.
Furthermore, there are many undefined name errors in your code, since you refer to names that are not defined in the current scope. Consider your function is_word_function(puzzle):
def is_word_found(puzzle):
if puzzle == answer:
return is_win
The name answer is defined in main(), whereas is_win is not defined at all (you are passing it to display_result() in main(), but have not defined it before). A better function declaration would look like this
def is_word_found(puzzle, answer):
return puzzle == answer
Note that this suggestion aims to be educational, I don't think that you necessarily need a function for this.
Generally, in order for names to be available in the current (function) scope, you have to either pass arguments to the function, or put them at module level, or - even better - consider looking into OOP (which, since this is a lab assignment, I suppose you haven't done yet).
Once you fixed these errors and your code compiles, you need to work on the logic of your game.
For example in play_game, you have the loop while num_guesses > 0 which will run infinitely, since you never decrease the num_guesses counter (in fact, you increase it in update_puzzle_string. A better loop would look like this:
def play_game(puzzle, answer, ..):
num_guesses = 4
while num_guesses and not is_word_found(puzzle, answer):
# logic
num_guesses -= 1
# or, alternatively
def play_game(puzzle, answer, ..):
num_guesses = 4
for _ in range(num_guesses):
# logic
if is_word_found(puzzle, answer):
# break or return
Consider to use flake8 in order to validate your code, detect errors and non-pythonic code constructs in the future.
>>> pip3 install flake8
>>> flake8 your_file.py
Related
I am a beginner to python and coding in general and I was wondering how I can make a print statement run before a module I imported. I am making a number guessing game and in my main file where I combine all the modules, I have a general function for running all the code together. It would be best if I show my code so you guys will have a better understanding of what I am dealing with:
import random
import lvl1
import time
level1 = lvl1.Level_1_activated()
# This is the main file combining everything together to make this game playable
introduction = """
Hello and welcome to NumGuess by Sava. Here is a little bit about the game:
The game works by having 3 levels, each where you must pick a number between a range of
1-10 (level 1), 1-20 (level 2), and 1-50 (level 3).
You are given 5 attempts in the first level, 10 in the second level, and 20 in the final one.
You can also access a hint by typing ‘hint’. You win the game by picking the right number in each level.
You lose the game when you run out of tries. You can get a free bonus with 5 extra tries if you type ‘hlp’.
"""
def start_game(time, lvl1):
print(introduction)
level1
start_game(time, lvl1)
This is just the code for the main module, I have the code for lvl1 (which is the first level of my 'game'), and I have a class which has all the functions which then take part in the while loop. I will also show that file:
import random
import time
# I will fist make variables for the time breaks. S is for short, M is for medium and L is for long
S = 0.2
M = 0.7
L = 1.1
class Level_1_activated():
def get_name(self):
# This function simply asks the name of the player
name = input("Before we start, what is your name? ")
time.sleep(S)
print("You said your name was: " + name)
def try_again(self):
# This asks the player if they want to try again, and shows the progress of the level
answer = (input("Do you want to try again? "))
time.sleep(M)
if answer == "yes":
print("Alright!, well I am going to guess that you want to play again")
time.sleep(M)
print("You have used up: " + str(tries) + " Of your tries. Remember, when you use 5 tries without getting the correct number, the game ends")
# Return statement for if the player wants to play again
return True
else:
print("Thank you for playing the game, I hope you have better luck next time")
# This is the return statement that stops the while loop
return False
def find_rand_num(self, random):
# This is the core of the level, where the player just chooses numbers between 1 and 10
time.sleep(S)
print("The computer is choosing a random number between 1 and 10... beep beep boop")
time.sleep(L)
# The list of numbers for the level that the player is on at the moment
num_list = [1,10]
number = random.choice(num_list)
ques = (input("guess your number, since this is the first level you need to choose a number between 1 and 10 "))
print(ques)
if ques == str(number):
time.sleep(S)
print("Congratulations! You got the number correct!")
# Yet another return statement for the while loop
return "Found"
elif input != number:
time.sleep(M)
print("Oops, you got the number wrong")
# This variable is fairly self-explanatory; it is what controls how many itterations there are in the while loop
tries = 1
while tries < 6:
if tries < 2:
Level_1_activated().get_name()
res = Level_1_activated().find_rand_num(random)
if res == "Found":
break
checker = Level_1_activated().try_again()
if checker is False:
break
tries += 1
If you go back to this function in the main file:
def start_game(time, lvl1):
print(introduction)
level1
I intentionally put the print statement before the module to make it run first, and I have tried different approaches to this and still can't seem to get a grasp on what I'm doing wrong here. Thank you for taking the time to read the code and I would be very grateful if any of you have a possible solution to this.
there are number of thing you can do, one is encapsulate your code into functions that only run when you ask for it
lvl1
... #all the previous code
def run_game():
tries = 1
while tries < 6:
...
tries += 1
you can also make a distinction between being executed directly vs being imported, to do that is simple, you include the following check (usually at the end of the file)
if __name__ == "__main__":
#if true it mean that you're executing this module directly, otherwise it was imported
#and you include here whatever you want that happens when you execute the module directly but not when is imported, like for example running a game
run_game()
__name__ is a special variable and python will assigned the value "__main__" if executed directly, otherwise it will be the name of the file, like "lvl1" for example
And in your main you can import it and do stuff like
import lvl1
...
def start_game():
print(introduction)
lvl1.run_game()
So I have been playing around with coding and so on and I just do like really random stuff, right now im doing so I just do random names inbuilt with my script basically Barry can turn to Henry or B.a.r.r.y. Nothing special.
The issue though is that whenever I try to print out or use name_q.get() in another method, it gives me a error saying NameError. What did go wrong?
def main():
names = name_q.get()
log(names)
exit()
def test():
name_q = Queue()
user_input = int(input('How many random names you wanna make out of Barry? [NUMBERS] \n'))
Names= "barry"
generator = NamesGenerator(Names).generate()
for i in range(0, user_input):
name_q.put(generator[i])
main()
The variable name_q is local to the function test. It doesn't exist in function main.
You have to give it as a parameter:
def main(name_q):
names = name_q.get()
log(names)
def test():
name_q = Queue()
user_input = int(input('How many random names you wanna make out of Barry? [NUMBERS] \n'))
names= "barry"
generator = NamesGenerator(names).generate()
for i in range(0, user_input):
name_q.put(generator[i])
main(name_q)
NB: this has nothing to do with your problem but please put capital letters only at the beginning of class names, not to any variable. If you don't, this will lead to misunderstanding when people read your code.
Moreover, Python code should be written with a maximum of 79 columns, as indicated in PEP8.
I'm new to Python and am really struggling to create a function for my quiz: I have created a while loop to offer different levels to the quiz player before they receive any questions. The while loop works on its own, but when i try to turn it into a function, the level variable stops working (returning only empty brackets outside of the code).
This is the while loop:
request_count = 0
level = ()
global_string_list = ()
while request_count < 1:
print user_level_options
level_request = raw_input("> ")
if level_request == "1":
level = string_1
global_string_list = string_1_list
if level_request == "2":
level = string_2
global_string_list = string_2_list
if level_request == "3":
level = string_3
global_string_list = string_3_list
if level_request == False:
print "Please try again."
request_count = request_count + 1
Could anybody please give me pointers on how to turn this into a function please?
Thank you!!
The level variable returns empty brackets because the level within the function is a local variable; completely different from the level you declared outside the function, which is outside the function's scope. This outside variable was hidden behind the local level variable, so all your assignments within the function were made to the local level and did not affect the level on the outside at all.
You have to either declare level as a global variable explicitly (generally considered bad practice) or you return your local level from the function. So perform all the changes you want in your function and then use the return statement like this:
def user_select(): # your function
#......your code goes here
return level
level = user_select() # the level variable within your function is now in this variable
I try to give you a jump start. But I won't give you the final solution.
In general, to make a function meaningful, you have to know why you need it.
I give you some example of the benefit using function.
Removal of repetitive code. (DRY, don't repeat yourself)
Identify a Pattern, and extract into a separate function. In your example, the repeating behavior can be seen near the condition inside the loop. (right after the raw_input function).
That is: if level_request == <something> then do <some-work>.
Thus, one improvement could be:
def updateLevel(level_request):
# Think about how you can determine the level without if-else
level = <?level?>
global_string_list = <?global_level|level?>
such that you only need to call:
while request_count < 1:
print user_level_options
level_request = raw_input("> ")
updateLevel(level_request)
if level_request == False:
print "Please try again."
request_count = request_count + 1
Abstraction
This is a very important topic in Computer Science and General Programming. You have to understand more to be able to appreciate the importance of abstraction.
E.g.
def askLevel():
print(user_level_options)
return raw_input("> ")
def displayError():
print("Please try again")
def incrementRequestCounter():
request_count += 1
such that you just need to call:
while request_count < 1:
level_request = askLevel()
updateLevel(level_request)
if level_request == False:
displayError()
incrementRequestCounter()
Note: in strict functional programming, function is a mapping of (input)->(output). And the function does not modify any global state (immutability). And all function must return a value. But in practice, we normally use a procedure instead. (procedure is a sequence of instruction). And def in python is both procedure and function.
myName = input("Hey there, what's your name?")
print("Hello",myName,"!")
print("Here's a game called ''Guess my number'', in this game you will have to guess my number in 5 tips, I will think of a number between 1 and 20.")
ready = input("Are you readyyyy!?")
if ready = "yes" or "yeah" or "totally" or "hell yeah" or "yupp" or "yepp" or "uhumm" or "sure": <-- here's the problem it says, at "sure"'s 1st "-sign
print("Let's go!")
loop = "y"
else:
print("I'm sorry to hear that.")
loop "n"
Could please anyone help, beginner here. I tried to delete and add new word, I restared the program and the computer because there's something clearly wrong. If I delete a word like "sure" the pointer will still point to the same exact place but there's nothing there...
You're using a single = sign in your if statement. That's not allowed. If you want to check for equality, you'll need to use ==. The = operator is only for assignment statements.
While changing = to == will fix the syntax error, your code still won't work exactly right. That's because == will not be distributed over all the or options you show. The expression a == b or c gets interpreted as (a == b) or c, and if c is "truthy" (as any non-empty string will be), the expression will be considered true.
Instead, you probably want to use something like if ready in {"yes", "yeah", "totally"}. This creates a constant set object and tests if the value of the ready variable is in the set (which is a fast check).
You are using a = instead of a == in your if statement. However, I would recommend doing if ready.lower() in {"yes", "yeah", "totally", "hell yeah", "yupp", "yepp"} to account for them using all uppercase.
Also, you seem to be missing your actual loop statements. I noticed you had variables named loop that are 'y' and 'n' but don't actually use them. You should also do something like this:
myName = input("Hey there, what's your name?")
print("Hello",myName,"!")
print("Here's a game called ''Guess my number'', in this game you will have to guess my number in 5 tips, I will think of a number between 1 and 20.")
loop = True
while loop:
ready = input("Are you readyyyy!?")
if ready.lower() in {"yes", "yeah", "totally", "hell yeah", "yupp", "yepp", "uhumm", "sure"}:
print("Let's go!")
loop = False
#To break out of the while loop that will keep asking them when they are ready
else:
print("I'm sorry to hear that.")
def dice():
import random
print("******************************")
print("***** DICE GENERATOR ******")
print("******************************")
#dice choice
user_select=int(input("""Choose the type of dice to roll.
(1)1d4
(2)1d6
(3)1d10
(4)1d12
(5)1d20
:"""))
if user_select==1:
dice=random.randint(1,4)
print(dice)
return
if user_select==2:
dice=random.randint(1,6)
print(dice)
return
if user_select==3:
dice=random.randint(1,10)
print(dice)
return
if user_select==4:
dice=random.randint(1,12)
print(dice)
return
if user_select==5:
dice=random.randint(1,20)
print(dice)
return
in the example code above if i give the input as 1 then a random number is generated but or anything else there is no return.I checked in the visualiser ,it is returning a None for all values except 1
This is because you are returning straight after the first condition. I would recommend reading a book on python and understand how functions and returns work.
http://www.learnpython.org/
You have to realise that functions end if any return statement is reached. Functions are small pieces of code that work together on a certain job/goal. Once they are done with it they can return stuff or just nothing, depending on the data types you are working with and the goal of the function.
In your case you need to put only one return after the last print statement.
As stated by others, the problem is that the return is not within the if block. A common way to do what you want is to use elif:
def dice():
import random
print("******************************")
print("***** DICE GENERATOR ******")
print("******************************")
#dice choice
user_select=int(input("""Choose the type of dice to roll.
(1)1d4
(2)1d6
(3)1d10
(4)1d12
(5)1d20
:"""))
if user_select==1:
dice=random.randint(1,4)
elif user_select==2:
dice=random.randint(1,6)
elif user_select==3:
dice=random.randint(1,10)
elif user_select==4:
dice=random.randint(1,12)
elif user_select==5:
dice=random.randint(1,20)
else:
dice=None
print(dice)
(edit) notice that a return statement is not needed at the end of a function because python will automatically return None here. Its harmless and some people prefer to have them.