0

So I am playing around with Turtle and I wanted to be able to create different turtles for a race, each with a different color.

I have a list with different names and colors in and I wished to take each of the names in the list

Turtle_names = ["tim", "bill", "ben", "alan", "william"]

And create a variable with the name, e.g.

tim = Turtle(shape="turtle)

I then wish to set the color from a similar list

Turtle_colors = ["red", "blue", "purple", "green", "yellow", "orange"]

I designed this which I had hoped would work, using the global() function to assign a variable with the name of a string in a list.

Turtle_names = ["tim", "bill", "ben", "alan", "william"]
Turtle_colors = ["red" "blue", "purple", "green", "yellow", "orange"]
Turtles = []

for i in range(len(Turtle_names)):
    new_turtle = Turtle_names[i]
    globals()[new_turtle] = Turtle(shape="turtle")
    new_turtle.color = Turtle_colors[i]
    Turtles.append(new_turtle)

I get an attribute error, on the new_turtle.color stating that a str had no attribute color.

Is there a simple fix to this code (e.g., some differing syntax for using global() in reference to OOP?) or is this concept the wrong approach?

My rational for this is I wish to have each turtle as a unique object for which I can extract values, e.g., the winning turtle from a race is tim, tim is red, therefore the red turtle won.

Now I can just call them the all the same thing, aka not using the names from the list, and get a similar effect like this;

for turtle_index in range(0, 6):
    new_turtle = Turtle(shape="turtle")
    new_turtle.color(Turtle_colors[turtle_index])
    Turtles.append(new_turtle)

But its more the specific of can what I am doing be done, or is it better to just assign a single variable name and append them to a list?

After all if a Turtle() is called tim its easier for me to know which Turtle() is "tim" than Turtles[7] being what would otherwise be called tim.

2 Answers2

1

Although @SunPodder already told you how to solve the problem, using globals() shouldn't be the correct approach. Creating variables dynamically is generally a bad idea, especially when you want to create a collection of similar objects.

A better solution is to store the Turtle objects in a dictionary. You should also loop through the names directly, instead of using range. Even better, is to loop through the pairs (name, color) using zip.

class Turtle:
    def __init__(self, shape):
        self.shape = shape

# Note: There are 5 names, but 6 colors (the 'orange' color will be ignored)
turtle_names = ["tim", "bill", "ben", "alan", "william"]
turtle_colors = ["red", "blue", "purple", "green", "yellow", "orange"] 
turtles = {}

for name, color in zip(turtle_names, turtle_colors):
    new_turtle = Turtle(shape="turtle")
    new_turtle.color = color 
    turtles[name] = new_turtle

E.g. then you can access the turtle named "tim" using turtles["tim"].

>>> turtles 

{'tim': <__main__.Turtle at 0x12b291880>,
 'bill': <__main__.Turtle at 0x12b291a60>,
 'ben': <__main__.Turtle at 0x12b2919a0>,
 'alan': <__main__.Turtle at 0x12b291190>,
 'william': <__main__.Turtle at 0x12b291e50>}

>>> turtles["tim"]

<__main__.Turtle at 0x12b291880>

>>> turtles["tim"].color
'red'

Lastly, I don't understand why the attribute color is not initialized in the constructor. If you define Turtle.__init__ as something similar to

class Turtle:
    def __init__(self, shape, color):
        self.shape = shape
        self.color = color 

You can just use a dictionary comprehension

turtle_names = ["tim", "bill", "ben", "alan", "william"]
turtle_colors = ["red", "blue", "purple", "green", "yellow", "orange"]

turtles = {name: Turtle(shape="turtle", color=color) 
           for name, color in zip(turtle_names, turtle_colors)}
Rodalm
  • 5,169
  • 5
  • 21
0

With new_turtle you are actually accessing a string and not a Turtle object.

Just change your code a litte bit. This works for me.

Turtle_names = ["tim", "bill", "ben", "alan", "william"]
Turtle_colors = ["red" "blue", "purple", "green", "yellow", "orange"]
Turtles = []

for i in range(len(Turtle_names)):
    globals()[Turtle_names[i]] = Turtle(shape="turtle")
    globals()[Turtle_names[i]].color = Turtle_colors[i]
    Turtles.append(globals()[Turtle_names[i]])
Sunlight
  • 165
  • 1
  • 11