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.
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()
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
Thanks firstly for bearing with me as a relative newcomer to the world of Python. I'm working on a simple set of code and have been racking my brain to understand where I am going wrong. I suspect it is a relatively simple thing to correct but all searches so far have been fruitless. If this has been covered before then please be gentle, I have looked for a couple of days!
I'm working on the following and after catching and correcting a number of issues I suspect that I'm on the last hurdle:-
def main():
our_list = []
ne = int(input('How many numbers do you wish to enter? '))
for i in range(0, (ne)): # set up loop to run user specified number of time
number=int(input('Choose a number:- '))
our_list.append(number) # append to our_list
print ('The list of numbers you have entered is ')
print (our_list)
main()
while True:
op = input ('For the mean type <1>, for the median type <2>, for the mode type <3>, to enter a new set of numbers type <4> or 5 to exit')
import statistics
if op == "1":
mn = statistics.mean(our_list)
print ("The mean of the values you have entered is:- ",mn)
if op == "2":
me = statistics.median(our_list)
print ("The median of the values you have entered is:- ",me)
if op == "3":
mo = statistics.mode(our_list)
print ("The mode of the values you have entered is:- ",mo)
if op == "5":
main()
else:
print("Goodbye")
break`
For some reason the appended (our_list) is not being recognised within the while true loop rendering the statistics calculation void. Any steer would be really appreciated as to where I am missing the obvious, thanks in advance.
Cheers
Bryan
I'm not sure exactly what you mean by "not being recognized", but our_list is a local variable inside main, so it can't be used anywhere but inside main.
So, if you try to use it elsewhere, you should get a NameError.
If your code actually has a global variable with the same name as the local variable that we aren't seeing here, things can be more confusing—you won't get a NameError, you'll get the value of the global variable, which isn't what you want.
The best solution here is to return the value from the function, and then have the caller use the returned value. For example:
def main():
our_list = []
ne = int(input('How many numbers do you wish to enter? '))
for i in range(0, (ne)): # set up loop to run user specified number of time
number=int(input('Choose a number:- '))
our_list.append(number) # append to our_list
print ('The list of numbers you have entered is ')
print (our_list)
return our_list
the_list = main()
while True:
op = input ('For the mean type <1>, for the median type <2>, for the mode type <3>, to enter a new set of numbers type <4> or 5 to exit')
import statistics
if op == "1":
mn = statistics.mean(the_list)
print ("The mean of the values you have entered is:- ",mn)
if op == "2":
me = statistics.median(the_list)
print ("The median of the values you have entered is:- ",me)
if op == "3":
mo = statistics.mode(the_list)
print ("The mode of the values you have entered is:- ",mo)
if op == "5":
the_list = main()
else:
print("Goodbye")
break
There are other options—you could pass in an empty list for main to fill, or use a global variable (or, better, a more restricted equivalent like an attribute on a class instance or a closure variable), or refactor your code so everyone who needs to access our_list is inside the same function… but I think this is the cleanest way to do what you're trying to do here.
By the way, this isn't quite the last hurdle—but you're very close:
After any mean, median, or mode, it's going to hit the "Goodbye" and exit instead of going back through the loop. Do you know about elif?
You mixed up '5' and '4' in the menu.
If the user enters 2 and 3 and asks for the mode, your code will dump a ValueError traceback to the screen; probably not what you want. Do you know try/except?
That's all I noticed, and they're all pretty simple things to add, so congrats in advance.
The issue is that our_list was defined in the main() function, and is not visible outside of the main() function scope.
Since you're doing everything in one chunk, you could remove line 1 and 6, taking the code from your main() function and putting it on the same indentation level as the code which follows.
This seems to be because you defined our_list within the main() function. You should probably define it as a global variable by creating it outside the main() function.
You could also put the while loop inside a function and pass in our_list as a parameter to the list.
I have the following program and the variable(dictionary) in question is player_info that stores player information (name and goals). In order to solve the error that results currently, I simply need to make player_info a global variable, but I was wondering if stackoverflow experts could suggest or discuss the possibility of alternate ways of solving this problem WITHOUT the use of global variables.
Code
#FOOTBALL COACH app
#The program allows a user to enter a number of players (their names and goals scored) and then search for a player, returning their average goals for the three matches
import sys
def main():
mainmenu()
def mainmenu():
print("=====WELCOME to the MAIN MENU=============")
print("""
1..........Add New Players & Goals
2..........Search by Players
3..........Quit
=========================================
""")
choice=int(input("Enter choice:"))
if choice==1:
addplayers()
elif choice==2:
searchplayer(player_info)
elif choice==3:
sys.exit()
else:
print("You must make a valid choice - 1, 2 or 3")
def addplayers():
player_info= {} #create a dictionary that stores the player name: player goals
num_players = int(input("Please enter number of players you wish to enter:"))
print ("You are entering %s players" %num_players)
player_data = ['Match 1 goals : ', 'Match 2 goals : ', 'Match 3 goals : ']
for i in range(0,num_players):
player_name = input("Enter Player Name :")
player_info[player_name] = {}
for entry in player_data:
player_info[player_name][entry] = int(input(entry)) #storing the marks entered as integers to perform arithmetic operations later on.
mainmenu()
def searchplayer():
print("===============SEARCH by player: Calculate average goals==================")
name = input("Player name : ")
if name in player_info.keys():
#print student_info
print ("Average player goals : ", str(sum(player_info[name].values())/3.0))
else:
print("Please enter a valid player name:")
main()
As mentioned, I am aware that re-writing this in the addplayer() sub would fix the problem:
global player_info
player_info = {} #create a dictionary that stores the player name: player goals
...I am looking for ways to solve the problem WITHOUT the use of global variables.
Update:
One answer below using return player_info is what I would like to go with, but it doesn't quite work yet. Also, I need to return to the main menu each time a player is added, not quite sure how to do this, without a mainmenu call each time. Any suggestions? https://repl.it/JRl5/1
You can use return inside your function to avoid using global variables. A simple example is shown below:
def addplayers():
player_info= {}
name = input("Enter Name: ")
test = int(input("Enter a number: "))
player_info[name] = test
return player_info
player_info = addplayers()
If you then wanted to use this in another function you would just pass in the dictionary as an argument to that function:
def searchplayers(player_info):
print (player_info)
Note: An interesting answer on "Why are global variables evil?"
Edit:
Your addplayers() was calling mainmenu() which itself was being calling within mainmenu(). This is a recursive function and it might be best to avoid these unless there's a good reason for having it. I would put the contents of mainmenu inside a while loop until some condition is met. The complete code is shown below (I have removed the main function as it wasn't really doing anything):
def mainmenu():
stop = False
while stop == False:
print("=====WELCOME to the MAIN MENU=============")
print("""
1..........Add New Players & Goals
2..........Search by Players
3..........Quit
=========================================
""")
choice=int(input("Enter choice:"))
if choice==1:
player_info = addplayers()
elif choice==2:
searchplayer(player_info)
elif choice==3:
print ("Exit the main menu")
stop = True
else:
print("You must make a valid choice - 1, 2 or 3")
def addplayers():
player_info= {} #create a dictionary that stores the player name: player goals
num_players = int(input("Please enter number of players you wish to enter:"))
print ("You are entering %s players" %num_players)
player_data = ['Match 1 goals : ', 'Match 2 goals : ', 'Match 3 goals : ']
for i in range(0,num_players):
player_name = input("Enter Player Name :")
player_info[player_name] = {}
for entry in player_data:
player_info[player_name][entry] = int(input(entry)) #storing the marks entered as integers to perform arithmetic operations later on.
return player_info
def searchplayer(player_info):
print("===============SEARCH by player: Calculate average goals==================")
name = input("Player name : ")
if name in player_info.keys():
#print student_info
print ("Average player goals : ", str(sum(player_info[name].values())/3.0))
else:
print("Please enter a valid player name:")
mainmenu()
Store everything related to the game in a data structure, for example a dictionary, and pass it along in all functions where it can be updated as needed. Write a function "newgame" that creates this structure and initialises it.
In a way, this is object-oriented programming without using Python's syntax for classes and objects. Probably, you will learn these later in your class / tutorial.
Firstly, it is always possible to avoid using global variables. Secondly, global variables are possibly a misnomer in Python; global stores the variable in the local globals, which is typically the local module. That avoids a large part of the problem languages like C have with globals, in that they collide; Python has a namespace per module. For a simple script, where there is only one context, that might be fine.
Another namespace you might use is that of a particular object, using a class. This might look like:
class Game:
def mainmenu(self,...):
self.addplayers()
def addplayers(self):
self.player_info = {}
With that sort of code, whoever instantiates Game can make multiple instances, each passed as self when used. This is in large part syntactic sugar for a similar form of mutable state passing:
def mainmenu():
state={}
addplayers(state)
def addplayers(state):
state['player_info'] = {}
For some forms of programming, immutable state is far preferable (in particular, multithreading where data is shared, or to keep a log where you can undo steps). That's done similarly but you make a new state for each call:
def mainmenu():
state = {}
state = addplayers(state)
def addplayers(oldstate):
newstate = oldstate.copy()
newstate['player_info'] = {}
return newstate
Python isn't designed for this and doesn't really have a mode to keep you from inadvertently modifying mutable types. Some types can be converted to similar types that are immutable, like frozenset or tuple.
One of the weirder hacks we can do is calling a Python function with a different set of globals than it normally has. This can be abused to take your existing functions, global statements and all, and have them use a different variable:
fakeglobals = mainmenu.__globals__.copy()
exec(addplayers.__code__, fakeglobals)
Your original code has calls back and forth between functions, though, and each of those will reset their globals per that __globals__ attribute.
Your code also implements a loop using tail recursion. This is not optimized in Python and will run out of stack space eventually. In languages where tail recursion is optimized, you can pass along state as arguments continously and need not return it.
I'm having issue with allowing a function to call on variables set by another function. I believe I know how to do this with single variables, but my code requires it be done with multiple variables, a challenge I've struggled with for hours. I've read much about ways others seem to have done this but I can't find success in implementing them.
#gathers the user's requests
def ask():
userw = int(input('How wide? '))
userh = int(input('How tall? '))
userc = input('What string to use? ')
userc_len = int(len(userc))
return (userw, userh, userc, userc_len)
#draws the rows of the box. First the top with the topbot function, then the body with body(), then the bottom with topbot again
def draw(w, h, c, c_len):
def topbot(w_, c_):
for x in range(w_):
print (c_, end ='')
print ('\n')
def body(w_, h_, c_, c_len_):
for x in range(h_-2):
print (c_, end = '')
for x in range(w_-2):
print(' ' * c_len_, end = '')
print (c_)
topbot(w, c)
body(w, h, c, c_len)
topbot(w, c)
#begins draw
draw(userw, userh, userc, userc_len)
The problem begins when the draw function tries to begin with the arguments of userw, userh, userc, userc_len, but can't find them:
NameError: name 'userw' is not defined
is returned when I try to run it.
Is it correct to define topbot and body within the draw function and manage the arguments how I did?
How do I return the four variables from ask in a manner such that draw can then use them as arguments?
ask() is a function which will return 4 values. So,
returnValues = ask()
draw = draw(*returnValues)
or simply, draw = draw(*ask())
Also, end = ' ' is not correct. Instead of that you can just use print(c_,'').
Include Validations wherever necessary. Like what if I type "hi" for "How wide?". In this case the program should tell me that this is wrong.
I was able to get draw() to accept the inputs from your ask() function (in Python IDLE) just by changing the last line of your code to this:
draw(*ask())
The * will unpack the variables from the ask() call and pass that along to draw(). The output looks kind of funny, and I'm not sure whether that's what you're looking for or not, but at least it got the variables in there correctly.