Question

I keep having the error

UnboundLocalError: local variable 'new_speedDx' referenced before assignment

while trying to run the following function:

def new_speedD(boid1):
    bposx = boid1[0]
    if bposx < WALL:
        new_speedDx = WALL_FORCE
    elif bposx > WIDTH - WALL:
        new_speedDx = -WALL_FORCE

    bposy = boid1[1]
    if bposy < WALL:
        new_speedDy = WALL_FORCE
    elif bposx > WIDTH - WALL:
        new_speedDy = -WALL_FORCE

    return new_speedDx, new_speedDy

In this function, boid1 is a vector with 4 elements (xpos, ypos, xvelocity, yvelocity) and all variables in upper case are constants (numbers). Anyone got an idea how to solve this? I've found many possible solutions on the internet but nothing seemed to work..

No correct solution

OTHER TIPS

It must be possible that bposx is neither less than WALL nor greater than WIDTH - WALL.

eg:

bposx = 10
WALL = 9
WIDTH = 200

if bposx < WALL:    # 10 is greater than 9, does not define new_speedDx 
    new_speedDx = WALL_FORCE
elif bposx > WIDTH - WALL:   # 10 is less than (200 - 9), does not define new_speedDx
    new_speedDx = -WALL_FORCE

Without seeing the rest of your program it's hard to suggest a reasonable fallback value, but you likely want to add something like:

else:
    new_speedDx = 0

What happens if neither of these conditions are true?

if bposx < WALL:
    new_speedDx = WALL_FORCE
elif bposx > WIDTH - WALL:
    new_speedDx = -WALL_FORCE

... new_speedDx is never assigned and so its value is indeterminate.

You can mitigate this by specifying what new_speedDx should be in this case:

if bposx < WALL:
    new_speedDx = WALL_FORCE
elif bposx > WIDTH - WALL:
    new_speedDx = -WALL_FORCE
else:
    new_speedDx = 0.

Explanation

As others have pointed out, you are not dealing with the case that WALL <= pos <= WIDTH - WALL.

Recommended change

Presumably the boid continues with current velocity if it does not hit a wall. Others have code that sets velocity to 0 if the boid is not hitting a wall. This solution is distinctive in using the existing velocity. I think that is important to your situation.

Code

def new_speedD(boid1):
    def new_speed(pos, velocity):
        return WALL_FORCE if pos < WALL \
            else (-WALL_FORCE if pos > WIDTH - WALL \
            else velocity)
    xpos, ypos, xvelocity, yvelocity = boid1
    new_speedDx = new_speed(posx, xvelocity)
    new_speedDy = new_speed(posy, yvelocity)
    return new_speedDx, new_speedDy

Some think this code is hard to understand. Here is a brief explanation:

  1. return WALL_FORCE if pos < WALL
  2. otherwise, return -WALL_FORCE if pos > WIDTH - WALL
  3. otherwise, return velocity

Here is a general question on the ternary operator. Remember, thought, that "It's frowned upon by some pythonistas."

If you don't use this code...

Return to your original and fix the typo in yvelocity case: bposx > WIDTH - WALL. The yvelocity does not depend on the xpos.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top