'Python/Turtle - How to execute a function on each sublist within a list

I am a complete Python newbie, my task is to create a function that will draw icons into a grid in turtle (900x600 grid, 5 columns and 4 rows, each square is 150x150 pixels). The type, position and orientation of the icons must be based on 4 given variables from a data set. The function has to be able to interpret a data set of the form:

data_set = [icon_style, bottom_left_column, bottom_left_row, orientation]

an example of a full data set, which draws 4 icons, is as follows:

data_set_03 = [['A', 1, 0, 'N'], ['C', 2, 1, 'E'], ['A', 3, 2, 'S'], ['A', 4, 3, 'W']]

Meaning the first icon is of type A, drawn at column 1, row 0, facing north. The second icon is of type C, drawn at column 2, row 1, facing East. etc etc, for all 4 icons in that list.

To tackle this challenge, first I defined a function to interpret the list and create 4 variables that will be used later by the function which draws the icons

def read_icons(w,x,y,z):
    if w == 'A':              
        icon = icon_01            
    elif w == 'B':           
        icon = icon_02
   elif w == 'C':
        icon = icon_03
    elif w == 'D':
        icon = icon_04


    if x == 0:
        x_coord = -450
    elif x == 1:
        x_coord = -300
    elif x == 2:
        x_coord = -150
    elif x == 3:
        x_coord = 0
    elif x == 4:
        x_coord = 150
    elif x == 5:
        x_coord = 300



    if y == 0:
        y_coord = -300
    elif y == 1:
        y_coord = -150
    elif y == 2:
        y_coord = 0
    elif y == 3:
        y_coord = 150



    if z == 'N':
        heading = 90
    elif z == 'E':
        heading = 0
    elif z == 'S':
       heading = 270
    elif z == 'W':
        heading = 180

Finally, I added this at the end of the function to test the drawing - I was planning to move this into my draw_icons function later

   icon()
   read_icons(*data_set_01)

icon() is what tells the function to draw the icon, so I can see if it is being drawn correctly, and read_icons(*data_set_01) executes the whole function based on data_set_01

This works well when drawing any SINGLE icon, The correct icon is drawn in the correct location, with the correct orientation. This works for any dataset such as

  data_set_01 = ['B', 1, 2, 'N']

Where only 1 icon is drawn.

However, my issue is that when I attempt to use a data set that contains information for more than one icon, such as

data_set_03 = [['A', 1, 0, 'N'], ['C', 2, 1, 'E'], ['A', 3, 2, 'S'], ['A', 4, 3, 'W']]

I run into a whole heap of errors.

The following is my best attempt at creating the draw_icons function, using a for each loop to run the read_icons() function once for each sub-list:

def draw_icons(data_set):
   for sublist in data_set:
     read_icons(*data_set)
     penup()
     goto(x_coord, y_coord)
     setheading(heading)
     pendown()
     icon()


draw_icons(data_set_03)

However this code results in the error:

 goto(x_coord, y_coord)
 NameError: global name 'x_coord' is not defined

Whereas my x_coord had no problem being defined when variables for only 1 icon were used.

My second attempt was to try to remove the for loop and explicitly run read_icons on each sub-list 1 by 1:

def draw_icons(data_set):
read_icons(*data_set[0])
penup()
goto(x_coord, y_coord)
setheading(heading)
pendown()
icon()

read_icons(*data_set[1])
penup()
goto(x_coord, y_coord)
setheading(heading)
pendown()
icon()

read_icons(*data_set[2])
penup()
goto(x_coord, y_coord)
setheading(heading)
pendown()
icon()

read_icons(*data_set[3])
penup()
goto(x_coord, y_coord)
setheading(heading)
pendown()
icon()

However the same error was encountered.

I was hoping that the draw_icons(data_set_03) would work as follows:

For the first sublist of data_set_03, that is: ['A', 1, 0, 'N'], define w,x,y and z based on the rules of read_icons(), then draw the icon as per these variables.

Next, move to the second sublist of data_set_03, that is: ['C', 2, 1, 'E'], re-define w,x,y and z based on the rules of read_icons() and draw the next icon as per these variables.

Rinse and repeat for sublists 3 and 4, until all 4 icons are drawn correctly.

Am I correct in thinking that data_set_03 is divided into the following sub-lists?

sublist 0 = ['A', 1, 0, 'N'] 
sublist 1 = ['C', 2, 1, 'E']
sublist 2 = ['A', 3, 2, 'S']
sublist 3 = ['A', 4, 3, 'W']

If so, why does my for loop not generate 4 variables from the first sub-list, drawn the icon, then overwrite the 4 variables with their new values from the second sub-list then drawn the second icon, etc etc.

Am I approaching this completely wrong? This is a beginner task, and so producing functioning code is the only requirement, however ugly it may be. I do not need to be elegant or concise as of yet. This has been my own honest attempt at completing the challenge, but have ran into a hurdle at this point.

Any assistance or insight into this would be greatly appreciated!



Solution 1:[1]

The code

def draw_icons(data_set):
   for sublist in data_set:
     read_icons(*data_set)
     penup()
     goto(x_coord, y_coord)
     setheading(heading)
     pendown()
     icon()


draw_icons(data_set_03)

is almost correct. There are two problems with this code though.

1: You pass the whole dataset into read_icons. This causes lists to pass into the read_icons function. The function either has the wrong number of arguments or the wrong kind of arguments. Try giving your read_icons the arguments *sublist.

2: Python variables have scope. You define x_coord, y_coord, heading, and icon within draw_icons meaning that they are invalid outside of the function draw_icons. I suggest you make the variables global (put them at the top of your code).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 DucksEL