Python 2.7: Variable defined in previous function, receiving undefined error - python-2.7

So my variable is clearly defined in inputnfo(), why am I getting an undefined error? The try & except perhaps? I've added removed... swapped it all around and cannot seem to find the solution, and answers online seem very situation based... Thanks in advance :)
Super New & improved edit: now getting UnboundLocalError
import random
alpha = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
strgen = []
retry = 0
### Defining
def inputnfo():
global much
much = input('how long do you want your random word/lucky number to be: ')
global which
which = raw_input('would you like letters or numbers?(let,num, or mix?):').lower
def generate():
while much > 0:
if which == 'let':
strgen.append(random.choice(alpha))
much -= 1
print '.'
elif which == 'num':
strgen.append(random.randint(1,9))
much -= 1
print '.'
elif which == 'mix':
mixer = random.choice([0,1])
if mixer == 0:
strgen.append(random.choice(alpha))
much -= 1
print '.'
elif mixer == 1:
strgen.append(random.randint(1,9))
much -= 1
print '.'
def finish():
finito = ''.join(strgen)
print 'Generation Completed!\n'
if which == 'let':
print 'Your randomly generated string is:' + finito
elif which == 'num':
print 'Your randomly generated number is:' + finito
elif which == 'mix':
print 'Your randomly generated Alpha-Numerical string is:' + finito
### Running
inputnfo()
while much != 0:
generate()
finish()

Its because the variable "much" in the function inputnfo() is local to that function alone. that is why you are getting an undefined error in the while loop. there is two solution
1. Make the variable "much" global by including the line
def inputnfo():
global much
try:
and then removing the argument of generate function
Or
2. Let the function inputnfo() return much and use this return value in the while loop and generate function
do the same for variable "which"
and put a line which = "" befor
which = ""
def inputnfo():
global much

Related

Faster "switch-case" implementation in python

I made the script below to read a string buffer and distribute the numbers in 6 different variables. I found an example doing the same in C# using switch-case method, and when I tried a similar method in python (as shown below) I got the desired result but it takes too much time to read the buffer (more than a second). This script is just a way to test the method, and it will be a part of a bigger open-loop control code, so the loop time is really important. Is there any faster way to do in in python? I use python 2.7. Thank you in advance.
Julio = '123.5,407.4,21.6,9.7,489.2,45.9/\n'
letter = ''
x_c = ''
y_c = ''
z_c = ''
theta_c = ''
ux_c = ''
uy_c = ''
variable_number = 1
def one():
global x_c
x_c += letter
def two():
global y_c
y_c += letter
def three():
global z_c
z_c += letter
def four():
global theta_c
theta_c += letter
def five():
global ux_c
ux_c += letter
def six():
global uy_c
uy_c += letter
def string_reader(variable_number):
switcher = {
1: one,
2: two,
3: three,
4: four,
5: five,
6: six
}
# Get the function from switcher dictionary
func = switcher.get(variable_number, lambda: 'Invalid variable number')
# Execute the function
print func()
for letter in Julio:
if (letter != '/') and (letter != ',') and (letter != '\n'):
string_reader(variable_number)
elif (letter == '/'):
break
elif (letter == '\n'):
break
else:
variable_number = variable_number + 1
print x_c, y_c, z_c, theta_c, ux_c, uy_c
Err... Aren't you overcomplicating things ?
>>> Julio = '123.5,407.4,21.6,9.7,489.2,45.9/\n'
>>> x_c, y_c, z_c, theta_c, ux_c, uy_c = Julio.strip().rstrip("/").split(",")[:6]

I have found most of everything I need and have a "mostly" working game

I having issues with the def check guess. It's the format my teacher specifically gave. You guys are great. Thanks for the help!!!! Sorry for the format this is my first time on this site.
# # Global variables
wrong_guesses = []
target_phrase = ""
current_phrase = ""
def clear_display():
for i in range(20):
print "\n"
def string_with_dashes(str):
global target_phrase
new_phrase = ""
for i in str:
if i.isalpha():
new_phrase += "-"
else:
new_phrase += i
return new_phrase
def check_guess(letter):
global current_phrase
replacement_list = [""]
for i in range(len(target_phrase)):
if target_phrase[i] == letter:
replacement_list[i] = target_phrase[i]
current_phrase = replacement_list
return current_phrase
else:
wrong_guesses.append(letter)
return False
def process_input():
user_letter = raw_input("Guess a letter: ").upper()
if user_letter in wrong_guesses:
print "You already guessed that letter"
user_letter = raw_input("Guess again : ")
else:
return check_guess(user_letter)
def one_turn():
global wrong_guesses
print "=================================================="
print current_phrase
print "Wrong guesses:", ' '.join(wrong_guesses)
print "Guesses remaining:", (8 - len(wrong_guesses))
display_robot(8 - len(wrong_guesses))
print "String to guess:", current_phrase
print "=================================================="
process_input()
print "\n\n"
def setup_phrase():
global target_phrase, current_phrase
target_phrase = raw_input("Dear friend, enter a phrase for the user to guess: ").upper()
current_phrase = string_with_dashes(target_phrase)
setup_phrase()
clear_display()
while True:
one_turn()
if len(wrong_guesses) > 7:
print "GAME OVER! You Lose"
breack
if current_phrase == target_phrase:
print "You WIN!!"
break
(why won't stackoverflow let me fix your code?)
I'm not sure exactly what you are trying to do, but it sounds like you want to create a string where the guessed letters replace blanks as they are guessed? Try something like this:
hidden_phrase = "abracadabra"
current_list = ["."]*len(hidden_phrase)
def check_guess(letter):
for i in range(len(hidden_phrase)):
if hidden_phrase[i] == letter:
current_list [i] = hidden_phrase[i]
print("before", "".join(current_list ))
check_guess("a")
print("guess1", "".join(current_list))
check_guess("z")
print("guess2", "".join(current_list))
check_guess("b")
print("guess3", "".join(current_list))
Output:
before ...........
guess1 a..a.a.a..a
guess2 a..a.a.a..a
guess3 ab.a.a.ab.a
In Python strings are immutable, and can't be updated, so it seems easier to me to keep the 'replacement' word (with blanks, which I represent with .) as a list, and join it back together for display.
The two global variables don't need to be explicitly specified as global, because the variable is not assigned to in the function, only accessed.
If you prefer to have a string current_phrase and update that, of course that's possible too:
hidden_phrase = "abracadabra"
current_phrase = "."*len(hidden_phrase )
def check_guess(letter):
global current_phrase
i = -1
while True:
i = hidden_phrase.find(letter, i+1)
if i<0:
break
current_phrase = current_phrase[0:i]+letter + current_phrase[i+1:]
print("before", current_phrase)
check_guess("a")
print("guess1", current_phrase)
check_guess("z")
print("guess2", current_phrase)
check_guess("b")
print("guess3", current_phrase)
This time you need the global again to prevent current_phrase = ... from creating a local variable.
My previous answer was to the first, more general, version of your question. Several things were wrong with your check_guess(). Here's a fixed version:
def check_guess(letter):
global current_phrase
replacement_list = list(current_phrase)
found=False
for i in range(len(target_phrase)):
if target_phrase[i] == letter:
replacement_list[i] = target_phrase[i]
found = True
if found:
current_phrase = "".join(replacement_list)
else:
wrong_guesses.append(letter)
Comments to show problems with your version:
def check_guess(letter):
global current_phrase
replacement_list = [""] # list has only 1 element, can't assign above index zero
for i in range(len(target_phrase)):
if target_phrase[i] == letter:
replacement_list[i] = target_phrase[i]
current_phrase = replacement_list # assigning a list to what was previously a string
return current_phrase # returns before checking 2nd character
else:
wrong_guesses.append(letter) # only the first character has been checked
return False # returns False or current_phrase, inconsistent
Also near the end you wrote breack instead of break, it's a shame that Python doesn't check these things by default, waiting instead for you to hit that line.

how to loop a set amount of times

Im writing a code that simulates the game word scrabble. What im trying to do is that it asks the user to unscrabble the word, and if they fail at it once they get another chance and so on for 3 chances. after 3 chances the program should tell them that they couldn't guess it within the chances limit and the program should tell them the word.
rand_artist = artist_names[random.randrange(len(artist_names))]
tries = 0
while tries < 3:
rand_input = enterbox("Unscrabble the following: {}".
format(txt), "Word Scrabble")
if rand_input != rand_artist:
msgbox("Try again!", "Word Scrabble")
tries +=1
elif rand_input == rand_artist:
msgbox("Congratulations! You guessed the word!")
tries +=3
elif tries > 2:
msgbox("You used up three chances! The word was {}".
format(txt), "Word Scrabble!")
Your code had several problems, some noted in my comment on the question. The following works as you seem to want.
from random import choice, shuffle
artist_names = ['Renoir', 'VanGogh', 'Rembrant', 'Homer', 'Pyle',]
artist = choice(artist_names)
alist = list(artist)
shuffle(alist)
scram = ''.join(alist)
for tries in range(1, 4):
guess = input("Unscrabble {}: ".format(scram))
if guess == artist:
print("Congratulations! You guessed the word!")
break
elif tries < 3:
print("Try again!")
else:
print("Failed three chances! The word was {}.".format(artist))

How to fix a program that only works once?

def check_answer(self, currentscore):
self.user_entry = self.user_entry.get_text()
if self.user_entry == self.books:
self.current += 1
self.total += 1
self.currentscore = self.current
print "right"
else:
print "wrong"
print self.currentscore
print self.total
When i run it and i put text a second time is says File "C:\Python27\guessing.py", line 16, in check_answer
self.user_entry = self.user_entry.get_text()
AttributeError: 'str' object has no attribute 'get_text'
Could someone explain it to me. Why it to me why it only works once. and also why doesn't the program execute the if statement. It only says wrong.
self.books = 'hello'
You overwrite the variable holding the reference to the text box with its contents. So when check_answer runs for the first time, self.user_entry is your text box, and you can call its method get_text() to retrieve the text entered by the user. Unfortunately, you assign this text to the same variable (self.user_entry =) - so you loose the reference to the text box. After the first call, self.user_entry is a string (instance of str class) retrieved at the first call.
Use a different variable name, like this:
def check_answer(self, currentscore):
self.user_entry_text = self.user_entry.get_text()
if self.user_entry_text == self.books:
self.current += 1
self.total += 1
self.currentscore = self.current
print "right"
else:
print "wrong"
print self.currentscore
print self.total
Also, possibly it doesn't have to be class's field, so you can also skip the self. part. In such case you could use the same name (user_entry), but for sake of readability it's better to call a variable with a name that says precisely what the variable holds:
user_entry_text = self.user_entry.get_text()
if user_entry_text == self.books:

python: checking for errors in the users input

I would like
to check if a string can be a float before I attempt to convert it to a float. This way, if the
string is not float, we can print an error message and exit instead of crashing the
program.
so when the user inputs something, I wanna see if its a float so it will print "true" if its not then it will print"false" rather than crashing. I don't want to use built in functions for this. I need to make my own function for this.
I tried :
import types
def isFloat():
x = raw_input("Enter: ")
if(x) == float:
print("true")
if(x) == str:
print("false")
isFloat()
I don't know if its true or not but it wont work it wont print anything either
The recommended thing to do here is to try it:
try:
f = float(x)
print("true")
except ValueError:
# handle error here
print("false")
This underscores the Python philosophy "It's better to ask for forgiveness than for permission".
The only reliable way to figure out whether a string represents a float is to try to convert it. You could check first and convert then, but why should you? You'd do it twice, without need.
Consider this code:
def read_float():
"""
return a floating-point number, or None
"""
while True:
s = raw_input('Enter a float: ').strip()
if not s:
return None
try:
return float(s)
except ValueError:
print 'Not a valid number: %r' % s
num = read_float()
while num is not None:
... do something ...
print 'Try again?'
num = read_float()