hangman: UnboundLocalError: local variable referenced before assignment
<p>I made a program to play hangman. I got pretty far but no matter how many times i try to fix it or make a different variation, the shell just comes up with the same thing.</p>

<p><code>UnboundLocalError: local variable '' referenced before assignment.
</code></p>

<p>I'm fairly new so can you make the answers as simple as possible. (or just a de-bugged version). </p>

<pre><code>import random
tries = 12
def intro ():
    print ('the size of your word is '+str(size))
    print ('you have ' + str(tries) + ' tries')
# word == car     output == '***'  
print (output)
def guesses ():
    guess = ('it')
    while len(guess) &gt; 1:
        guess = str(input('pick a letter ')) 

if guess not in word:
    print ('incorrect')
    tries = tries - 1
    print ('you have ' + str(tries) + ' tries')

if guess in word:
    print ('correct!!')
    tries = tries - 1
    position = word.index(guess)
    output = output[:position] + guess + output[position+1:]
    print ('you have ' + str(tries) + ' tries')

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
intro ()    

while output != word or tries != 0:
    guesses ()
    print (output)
</code></pre>

<p>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. </p>

<p>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 <em>and</em> the function's arguments if any. </p>

<p>When a name is used <em>but not defined</em> 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. </p>

<p><strong>BUT</strong> - 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) <em>anywhere</em> 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 <em>explicitely</em> tell Python this name should be considered global using the <code>global</code> statement, ie:</p>

<pre><code>bar = 42

def foo():
   global bar
   bar = "baaz"
</code></pre>

<p>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:</p>

<pre><code>&gt;&gt;&gt; baaz = 42
&gt;&gt;&gt; def foo():
...     baaz = 84
... 
&gt;&gt;&gt; print(baaz)
42
&gt;&gt;&gt; foo()
&gt;&gt;&gt; print baaz
42
&gt;&gt;&gt; 
</code></pre>

<p>But if you try to access the name before the line where it's defined, you will get this <code>UnboundLocalError</code>, because (by definition) before the assignment the (local) name is not bound to any value:</p>

<pre><code>&gt;&gt;&gt; baaz = 42
&gt;&gt;&gt; def foo():
...     print(baaz) # wont print the global 'baaz' but raise an UnboundLocalError
...     baaz = 84 # because this line defines `baaz` as a local
... 
&gt;&gt;&gt; foo()
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
  File "&lt;stdin&gt;", line 2, in foo
UnboundLocalError: local variable 'baaz' referenced before assignment
</code></pre>

<p>Now you can check your own code and find the at least three places where you <em>do</em> have this pattern (hint: in assignments, the right hand side of the <code>=</code> symbol is executed <em>before</em> the assignment itself).</p>

<p>You <em>could</em> (technically) "solve" this using the <code>global</code> statement but this is definitly <em>not</em> the right thing to do, at least if you hope to learn to write good (ie: readable, maintainable) code. </p>

<p>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.</p>

<p>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:</p>

<pre><code>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) &gt; 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()
</code></pre>

python debugging