Apart for your snippet's indentation being off (remember that in python indentation is part of the syntax so take care about this when posting snippets), your main problem is with global vs local namespace.
The global namespace holds "top level" names (names defined at the top level of your script / module, IOW outside a function), the local namespace ("local" to a function's body) holds names defined within the function's body and the function's arguments if any.
When a name is used but not defined within a function's body, it is looked up in the global namespace, so a function can access names that have not been explicitely defined in it's local namespace.
BUT - and here comes the tricky part: "defined within the function's body" means there is an assignment to that name within the function (using one of "=", "+=", "-=", "/=" etc) anywhere in the function's body - the fact that there's a synonym in the global namespace doesn't magically make the name global, so if you really want to assign to a global name within a function (which is almost always a very bad idea, google "globals evil" for more on this), you have to explicitely tell Python this name should be considered global using the global
statement, ie:
bar = 42
def foo():
global bar
bar = "baaz"
Trying to assign to global name without declaring it as global will always make the name local. If you don't try to access that name before the assignement, you will have no explicit error (the program is technically correct) but you may not have the expected result since the global name won't be affected (which a logical error, and usually harder to debug), ie:
>>> baaz = 42
>>> def foo():
... baaz = 84
...
>>> print(baaz)
42
>>> foo()
>>> print baaz
42
>>>
But if you try to access the name before the line where it's defined, you will get this UnboundLocalError
, because (by definition) before the assignment the (local) name is not bound to any value:
>>> baaz = 42
>>> def foo():
... print(baaz) # wont print the global 'baaz' but raise an UnboundLocalError
... baaz = 84 # because this line defines `baaz` as a local
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
UnboundLocalError: local variable 'baaz' referenced before assignment
Now you can check your own code and find the at least three places where you do have this pattern (hint: in assignments, the right hand side of the =
symbol is executed before the assignment itself).
You could (technically) "solve" this using the global
statement but this is definitly not the right thing to do, at least if you hope to learn to write good (ie: readable, maintainable) code.
The good news is that you actually almost never have to modify a global variable (and I'm saying this from years of experience writing / maintaining real life full-blown applications) - you just have to 1/ pass relevant arguments to your functions and 2/ return relevant values from your functions. The top-level code of your scripts / module should only contains imports and functions / classes / constants defitions, and if it's a script a "main" function and a call to this function.
As an example here's a quick rewrite of your script without a single global variable - there's still a lot of room for improvement but at least it works, and it works without globals:
import random
def intro(tries, size):
print ('the size of your word is {}'.format(size))
print ('you have {} tries'.format(tries))
def guesses(word, tries, output):
guess = ('it')
while len(guess) > 1:
guess = str(raw_input('pick a letter '))
if guess not in word:
print('incorrect')
tries = tries - 1
print('you have {} tries'.format(tries))
else:
print('correct!!')
tries = tries - 1
print('you have {} tries'.format(tries))
position = word.index(guess)
output = output[:position] + guess + output[position+1:]
return tries, output
def main():
print ('this is a game of hangman where you get a word')
print ('that you have to guess letter by letter')
print ('')
print ('')
word_list = ['jazz', 'whale', 'surgery', 'love']
word = random.choice(word_list)
size = len(word)
output = '*' * size
tries = 12
intro(tries, size)
while not (output == word or tries == 0):
tries, output = guesses(word, tries, output)
print(output)
main()