Defining function difficulties ["NameError: name 'number' is not defined"] - python-3.x

Okay, trying to make a simple game of Guessing Numbers but I can't find the mistake in this code. Still pretty new to python so probably the reason why but I can't figure out what is wrong with it.
import random
from time import sleep
def start():
print("Welcome To The Guessing Game \n Try to guess the number I'm thinking of \n Good luck!")
selectRandomNumber()
guessCheck(number, numberInput=1)
def restart():
print("Creating new number ...")
sleep(1)
print("OK")
selectRandomNumber()
guessCheck(number,numberInput=1)
def selectRandomNumber():
number = random.randint(0,1000)
tries = 0
return
def tryAgain():
while True:
try:
again = int(input("Do you want to play again? y/n:"))
except ValueError:
print("Couldn't understand what you tried to say")
continue
if again == "y" or "yes":
print("Awesome! Lets go")
restart()
elif again == 'n' or "no":
print("Goodbye!")
break
else:
print("Not a valid option")
continue
def guessCheck(number,numberInput=1):
while True:
try:
numberInput = int(input("What number do you think it is?: "))
except ValueError:
print("Couldn't understand that. Try again")
continue
if numberInput > number:
print("Too high")
tries += 1
continue
elif numberInput < number:
print("Too low")
tries += 1
continue
elif numberInput == number:
print("Congrats! You got my number")
tryAgain()
number = selectRandomNumber()
print(number)
start()
Every time I try to run the program I keep getting the same mistake.
It tells me:
Traceback (most recent call last):
File "python", line 60, in <module>
start()
File "python", line 8, in start
guessCheck(number, numberInput)
NameError: name 'number' is not defined
Don't quite understand what that means.
Some help would be appreciated. Thanks!
* UPDATE *
Was able to fix the part about defining the variable but now new problem happened where when I try to run
Same code as before but added
guessCheck(number,numberInput=1)
and also added the variable number at the end
number = selectRandomNumber()
print(number)
start()
when I run it I get this
None # this is from `print(number)` so instead of getting a number here I'm getting `None`
Welcome To The Guessing Game
Try to guess the number I'm thinking of
Good luck!
What number do you think it is?:

The Traceback is telling you this:
We got to start().
start() called guessCheck().
We tried to pass two pieces of information to guessCheck(): the variable names number and numberInput.
We don't have those variables defined yet! numberInput doesn't get defined until once we've already started guessCheck(), and number isn't actually defined anywhere.
As Manoj pointed out in the comments, you probably want number to hold the output of selectRandomNumber(). So, instead of just calling selectRandomNumber() in start(), try number = selectRandomNumber() instead.
You can add a print(number) on the line right after that to make sure number has a value assigned to it.
Now number has a value, going into your call to guessCheck(). That still leaves numberInput undefined though. You can set a default value for function arguments like this:
guessCheck(number, numberInput=1)
That way, when guessCheck is called but numberInput hasn't been defined yet, it will automatically give it the value 1 until you set it explicitly.
You may encounter other issues with your code the way it is. My advice would be to start really simply - build up your game from each individual piece, and only put the pieces together when you're sure you have each one working. That may seem slower, but trying to go too fast will cause misunderstandings like this one.

Related

Functions that include input/print

I'm writing a program where you can play blackjack with a computer. I've implemented a class, a "main" and a bunch of others functions. The problem is that almost all of my them are build to get the proper input from the user. For instance:
def get_the_answer():
while True:
answer = input("Write 'reveal' to reveal cards, 'add' to add one more: ")
if answer in ['reveal', 'add']:
break
else:
continue
return answer
Or this one, which also has some prints in it:
def start_and_greet():
print('', colored('Hi! Shall we play Blackjack?', 'yellow'), '', sep='\n')
print(colored(blackjack()))
print()
while True:
answer = input("Write 'start' / 'exit': ")
if answer in ['start', 'exit']:
break
else:
continue
return answer
If I put all my inputs and prints in "main" function, there will be almost no additional functions besides "main", so this won't be acceptable by the task.
The main reason why I'm worrying about it is that I don't understand how one should test this...
Thank you in advance for your help!
I know that it is not recommended to use a function with print / input, although I saw how David Malan (CS50P course) uses the similar one in lectures:
def get_number():
while True:
n = int(input("What's n? "))
if n > 0:
break
return n

Require user input until is correct [duplicate]

This question already has answers here:
Asking the user for input until they give a valid response
(22 answers)
Closed 2 years ago.
What is the best way of repeatedly asking for the user for correct input?
For example I'd like to continue checking if the a value is an int or not and when it is finally say ok you picked number.
I'm stuck here:
try:
a = int(input())
except:
print("incorrect pick a number and try again")
#Somewhere here
print("Ok thanks you finally picked a number")
The only exception you want to catch is the ValueError raised by int should it not be able to convert its argument to an integer. The try statement will be in a loop that you will explicitly break out of if you don't get an exception.
while True:
response = input()
try:
a = int(response)
except ValueError:
print("incorrect pick a number and try again")
else:
print("Ok thanks you finally picked a number")
break
if you want/must mantain this code, i think the unique way is using a loop.
while True:
try:
a = int(input('Insert a number:'))
print ('Your number is {}'.format(a))
break
except ValueError:
print("incorrect pick a number and try again")
So if the user inserts an integer, the code prints number and break the loop else repeats the request.
I hope it's useful for you!
You can do it like this:
a = None
while type(a) != int:
try:
a = int(input())
except:
print("incorrect pick a number and try again")
print("Ok thanks you finally picked a number")
Essentially:
Create a variable with NoneType so when you first run the program it can access the while loop because the conditions meats.
Loop until the type of that variable is not int.
Request the user input and try to cast as integer, if it fails print an error and try again.
When the input is of integer type it exit the loop and print the final message.
You can use type() or isinstance() to check, but as suggested by #chepner avoid the usage of type because it simply returns the type of an object whereas, isinstance() returns true if the object argument is an instance of the classinfo argument, or of a (direct, indirect or virtual) subclass thereof.
To help you understand:
class foo:
pass
class bar(foo):
pass
isinstance(foo(), foo) # returns True
type(foo()) == foo # returns True
isinstance(bar(), foo) # returns True
type(bar()) == foo # returns False,and this probably won't be what you want.
In the case you want to use isinstance() the code will result as:
a = None
while not isinstance(a, int):
try:
a = int(input())
except:
print("incorrect pick a number and try again")
print("Ok thanks you finally picked a number")
As pointed out by #L3viathan you can also do:
a = None
while a is None:
try:
a = int(input())
except:
print("incorrect pick a number and try again")
print("Ok thanks you finally picked a number")
In this case you loop until a get a value, that will be done only if the exception is not thrown.
while True:
try:
number=int(input("Enter a number: "))
except:
print("incorrect pick a number and try again")
else:
print("ok Thanks you finally picked a number ")
break

Code runs on command prompt but not on hydrogen

I'm just beginning with programming(python3), using the information available on Internet. Right now I'm learning how to use try/except. My problem is that the code I wrote runs fine in the command prompt of windows 10, but not in the shell(Atom/Hydrogen) where it throws an error(line 6, NameError) because I didn't defined the variable "fish", I know that usually happened the other way around but I just want to understand if I'm making a mistake. The code is as follows:
>try:
>> fish = int (input("please enter your age "))
>except:
>> print("That's not a number ")
>> exit(0)
>if fish <= 15:
>> parentLicense = input ("have one of your parents have a license? (yes/no) ")
>> if parentLicense == "yes":
>>> print ("You can fish")
>> else:
>>> print("So sad, you or one of your parents need a license")
Hi Chiron and welcome to the community. The reason you are getting an undefined error is because fish can be undifined under certain circumstances in the try statement.
You should use
try:
# try stuff
except ValueError:
# do stuff when theres an error
else:
# stuff if try stuff works
else is only called if no exception is raised. I would avoid using bare except too as it can cause issues and its not good practice.

Python code does not come out when first return statement is executed

enter image description hereI am a begineer in Python development and learning python on python 3.6
When I executed below code ,I expected it to terminate when first return statement is executed and I was expecting Output 4.
But It is iterating 3 times and giving output as 8.
As per my understanding as soon as return statement is executed it should come out of the function. Why this is not happening.
#!/bin/python3
def stockmax(prices):
# Write your code here
# Write your code here
count=0
profit=0
maximum=max(prices)
#print(maximum)
index_max=prices.index(maximum)
#print(index_max)
if len(prices)<=1:
return(profit)
else:
for i in range(len(prices)):
if i<index_max:
profit=profit-prices[i]
#print("profit if",profit)
count=count+1
#print("count is",count)
elif i==index_max:
#print(profit)
profit=profit+(prices[i]*count)
#print("profit elif",profit)
count=0
else:
profit=profit+stockmax(prices[i:])
return(profit) # should terminate on executing first return
x=(stockmax([5,4,3,4,5]))
print(x)
By calling stockmax inside of itself, you are opening up a new 'scope'. We can treat these as levels on a building. When you call it, you are essentially moving up a floor, or gaining a level. To get back to the ground floor, or the main 'scope' you need to go back through all of the lower floors. We can do this easily by using return a little bit sooner. In your code it would look a little like this:
def stockmax(prices):
count=0
profit=0
maximum=max(prices)
index_max=prices.index(maximum)
if len(prices)<=1:
return(profit)
else:
for i in range(len(prices)):
if i<index_max:
profit=profit-prices[i]
count=count+1
elif i==index_max:
profit=profit+(prices[i]*count)
count=0
else:
profit=profit+stockmax(prices[i:])
return(profit) # Use return here instead!
This would give us the desired output of 4.

Memory game timer implementation and error handling

I've implemented a memory game where the user has to sort numbers in his head while a timer of 5 sec is running.
Please see code below:
from random import randint
from threading import Timer
def timeout():
print("Time over\n#####################\n")
while True:
list = []
for i in range(5):
list.append(randint(1000, 10000))
t = Timer(5, timeout)
t.start()
print(list)
print('[ 1 , 2 , 3 , 4 , 5 ]')
solution = sorted(list)[2]
print('please select the 3rd largest number in this row (1-5):')
input_string = input()
selection = int(input_string)
if solution == list[selection - 1]:
print("Your guess is correct\n")
else:
print("Your guess is wrong\n")
t.join()
Here is the game interaction itself (please ignore the syntax highlighting):
USER#HOST:~/$ python3 memory_game.py
[8902, 8655, 1680, 6763, 4489]
[ 1 , 2 , 3 , 4 , 5 ]
please select the 3rd largest number in this row (1-5):
4
Your guess is correct
Time over
#####################
[5635, 3810, 1114, 5042, 1481]
[ 1 , 2 , 3 , 4 , 5 ]
please select the 3rd largest number in this row (1-5):
4
Your guess is wrong
Time over
#####################
[6111, 1430, 7999, 3352, 2742]
[ 1 , 2 , 3 , 4 , 5 ]
please select the 3rd largest number in this row (1-5):
23
Traceback (most recent call last):
File "memory_game.py", line 24, in <module>
if solution == list[selection - 1]:
IndexError: list index out of range
Time over
#####################
Can anybody help me with these things:
1. 'Time over' should only be written if the player needs more than 5 sec for the answer. If the player solves it in time the next challenge should appear silently.
2. If the player does not write any guess and presses 'Enter' the program terminates with error message:
Traceback (most recent call last):
File "memory_game.py", line 22, in
selection = int(input_string)
ValueError: invalid literal for int with base 10:''
3. If the player enters any random number the program quits with an 'Index out of range error' - I couldn't find out where to put try: except:
Any help would be appreciated - Thanks!
As for your questions:
You can accomplish that with t.cancel() (stop the timer and do not call the function) instead of t.join() (wait until the thread has finished; this will ALWAYS result in a timeout, of course)
(and 3.) These are basically the same -- put the query message and all input handling into a while loop, and break out of it once you know that the input is valid
...
As an extra, the "time over" message wasn't really doing anything useful (e.g. you could still enter a valid answer after the time over occurred. I "fixed" that in a brute force way by making the program exit if the timeout is hit. Instead of doing that, you can also use a global variable to store whether the timeout was hit or not and handle that in your input accordingly (make sure to make it threadsafe using e.g. a mutex).
In general, it might be easier to turn around the structure of the program -- let the main thread handle the timeout and verification of the input, let the thread only handle the input (this way, it's easy to kill the thread to stop the input from being handled).
Of course, using the select module, one could implement this even nicer without threads (have one pipe that gets written to by a thread/timer, and the standard input, then select both for reading and it will block until either user input or the timeout occurs).
And maybe someone will post a nice asyncio-based solution? ;)
Here's the modified solution (modifying only as little as possible to get it to work, one could refactor other parts to make it nicer in general):
import random
import threading
import os
def timeout():
print("Time over\n#####################\n")
# You can't use sys.exit() here, as this code is running in a thread
# See also: https://stackoverflow.com/a/905224/1047040
os._exit(0)
while True:
list = []
for i in range(5):
list.append(random.randint(1000, 10000))
t = threading.Timer(5, timeout)
t.start()
print(list)
print('[ 1 , 2 , 3 , 4 , 5 ]')
solution = sorted(list)[2]
while True:
try:
print('please select the 3rd largest number in this row (1-5):')
input_string = input()
selection = int(input_string)
chosen = list[selection - 1]
# If we arrive here, the input was valid, break out of the loop
break
except Exception as e:
# Tell the user that the input is wrong; feel free to remove "e"
# from the print output
print('Invalid input:', e)
if solution == chosen:
print("Your guess is correct\n")
else:
print("Your guess is wrong\n")
# Make sure to cancel the thread, otherwise guessing correct or wrong
# will block the CLI interface and still write "time out" at the end
t.cancel()

Resources