0

I'm confused. What is different about player1_head compared to the other variables I am printing in the code below? As far as I can tell it should behave the same as the others - it's declared in the global scope, no? I don't think it's a typo.

UnboundLocalError: local variable 'player1_head' referenced before assignment

from turtle import *
from random import randint
from utils import square, vector

player1_xy = vector(-100, 0)
player1_aim = vector(4, 0)
player1_body = []
player1_head = "It looks like I'm assigning here."

def draw():
    "Advance player and draw game."
    print("xy: ", player1_xy)
    print("head: ", player1_head)
    print("body: ", player1_body)
    player1_xy.move(player1_aim)
    player1_head = player1_xy.copy()
    player1_body.append(player1_head)
    square(player1_xy.x, player1_xy.y, 3, 'red')
    update()
    ontimer(draw, 200)

setup(420, 420, 370, 0)
hideturtle()
tracer(False)

draw()
done()
2

2 Answers 2

2

Because you failed to declare player1_head as a global, in the draw() function it appears to that function that you're printing out local variable player1_head before it has a value:

print("head: ", player1_head)
# ...
player1_head = player1_xy.copy()

Instead do:

def draw():
    """ Advance player and draw game. """

    global player1_head

    print("xy: ", player1_xy)
    print("head: ", player1_head)
    print("body: ", player1_body)
    player1_xy.move(player1_aim)
    player1_head = player1_xy.copy()
    player1_body.append(player1_head)

    square(player1_xy.x, player1_xy.y, 3, 'red')

    update()
    ontimer(draw, 200)
Sign up to request clarification or add additional context in comments.

4 Comments

No "appears" about it; the presence of an assignment makes player1_head a local variable throughout the scope where the assignment takes place. Locality is not determined on a per-statement basis.
@chepner, I wasn't expressing doubt, I meant it appears to the draw() function that player1_head is local, not that it appears to me. I'll clarify the text.
But why only that variable needs declaring as global inside the function, not the others?
@Robin, only that variable needs to be declared global because it is being reset to a new value, the other variable are only being examined or having their methods called. Read up on the Python global keyword -- it is often misunderstood.
0

The assignment player1_head = player1_xy.copy() in the draw() function is saying to Python that the variable player1_head is a local variable to the function draw(), and since print("head: ", player1_head) is referencing a local variable before its assignment, the error is shown. You can fix this by using player1_head as a global variable (since you're modifying it, same goes for the variable player1_body, since you're doing player1_body.append(player1_head)), like so:

def draw():
    "Advance player and draw game."
    global player1_head
    #...rest of the code

Note however that you should avoid using global variables when possible, this is one the problems that arises from using them (they can be modified by any function, which can sometimes lead to errors and confusions).

1 Comment

So even though the print statement comes before the assignment of player1_head in the function, it is still treated as local even though it exists in the global scope? This seems like non-obvious behaviour to me. Something about the order in which the interpreter processes statements within a function?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.