Python Forum

Full Version: local / global lists
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
So I coded a Program in python whith PyGameZero and the mu editor
def animate_nodes():
    for current_node in node_list:
        x = current_node[0] + current_node[2]
        y = current_node[1] + current_node[3]
        
        if current_node[2] > 0 and current_node[2] < 10:
            vx = current_node[2] + random.randrange(-1, 1)
            
        if current_node[3] > 0 and current_node[3] < 10:
            vx = current_node[3] + random.randrange(-1, 1)
        
        new_node_list.append = [x, y, vx, vy]
    
    node_list = new_node_list.copy()
This is one part of my programm.
Now Im getting this error:
UnboundLocalError: local variable 'node_list' referenced before assignment

Now I now what global and local variables are but the variable node_list is a global one in my program so I don't understand why this happens.

for better context here the whole code (its supposed to animate a few nodes that get connected when they are in a particular range to each other and move the nodes by a few pixel every frame):
import random
import math

WIDTH = 1280
HEIGHT = 720

# defines the number of nodes visible on the screen (+ 1)
node_count = 30

# defines the range in which the nodes will connect
connection_range = 150

# stores the x and y coordinates of the nodes
node_list = []

# stores the x and y values of the vectors
connection_list = []

others_list = []
    
# creates the nodes
for i in range(0, node_count):
    # generate random coordinates
    x = random.randrange(1, 1280)
    y = random.randrange(1, 720)
    vx = random.randrange(0, 10)
    vy = random.randrange(0, 10)
    # adds these x and y values to the nodelist
    node_list.append([x, y])
    
    


def calculate_connections():
    others_list = node_list.copy()
    # after we have created the nodes we go over the nodes one by one
    for current_point in others_list:
        
        others_list.remove(current_point)
        # then we look at all the resting nodes (except for the current one) and we compare the distances
        # this is a so called nested loop (verschachtelte Schleife)
        
        for other_point in others_list:

        # coords_temp = []
            x_temp = other_point[0]
            y_temp = other_point[1]
            x = current_point[0]
            y = current_point[1]

            # calculate the vector between the current and the other nodes
            vector_x = abs((x - x_temp))
            vector_y = abs((y - y_temp))

            vector_length = math.sqrt(vector_x ** 2 + vector_y ** 2)
            
            print(vector_length)
            # compare set connection range to vector range
            if vector_length <= connection_range:
                connection_temp = []
                connection_temp.append([x, y])
                connection_temp.append([x_temp, y_temp])
                connection_list.append(connection_temp)

def animate_nodes():
    for current_node in node_list:
        x = current_node[0] + current_node[2]
        y = current_node[1] + current_node[3]
        
        if current_node[2] > 0 and current_node[2] < 10:
            vx = current_node[2] + random.randrange(-1, 1)
            
        if current_node[3] > 0 and current_node[3] < 10:
            vx = current_node[3] + random.randrange(-1, 1)
        
        new_node_list.append = [x, y, vx, vy]
    
    node_list = new_node_list.copy()
    

# draws the Frame
def draw():
    calculate_connections()
    # draw the background
    screen.fill((255, 255, 255))

    # draws the nodes
    for i in range(node_count):
        screen.draw.filled_circle(node_list[i-1], 3, (125, 125, 125))

    # draw the connections
    for line in connection_list:
        print(line)
        screen.draw.line(line[0], line[1], (0, 0, 0))
        
    animate_nodes()
I hope you can help me :)
thanks in advance <3
This is an odd case. You have a global "node_list", and if you left out the assignment at the end of animate_nodes, Python would use the global "node_list" and the code would run (well, eventually). The assignment changes things. The assignment creates a local variable named "node_list".
def animate_nodes():
    for current_node in node_list:  # node_list is a local variable.
        x = current_node[0] + current_node[2]
        y = current_node[1] + current_node[3]
         
        if current_node[2] > 0 and current_node[2] < 10:
            vx = current_node[2] + random.randrange(-1, 1)
             
        if current_node[3] > 0 and current_node[3] < 10:
            vx = current_node[3] + random.randrange(-1, 1)
         
        new_node_list.append = [x, y, vx, vy]
     
    node_list = new_node_list.copy()  # Assignment makes a local node_list
Use "global" to inform python you want to use the global variable
def animate_nodes():
    global node_list
    for current_node in node_list:  # node_list is a local variable.
        x = current_node[0] + current_node[2]
        y = current_node[1] + current_node[3]
         
        if current_node[2] > 0 and current_node[2] < 10:
            vx = current_node[2] + random.randrange(-1, 1)
             
        if current_node[3] > 0 and current_node[3] < 10:
            vx = current_node[3] + random.randrange(-1, 1)
         
        new_node_list.append = [x, y, vx, vy]  # This is the next bug
     
    node_list = new_node_list.copy()  # Assignment makes a local node_list
Better yet, avoid using the global variable. Pass the variable as an argument and return the modified variable. This exposes the purpose of the function instead of hiding it as a side effect.
def animate_nodes(node_list):
    """Where is my docstring?"""
    new_list=[]
    for current_node in node_list:
        x = current_node[0] + current_node[2]
        y = current_node[1] + current_node[3]
        vx = 0  # Default values?
        vy = 0  # Used but never assigned
         
        if current_node[2] > 0 and current_node[2] < 10:
            vx = current_node[2] + random.randrange(-1, 1)
             
        if current_node[3] > 0 and current_node[3] < 10:
            vx = current_node[3] + random.randrange(-1, 1)
         
        new_list.append = [x, y, vx, vy]
     
    return new_list