Beginners guide to Iteration in python

The basics of dealing with many things in code.

gaetanlee [CC BY (https://creativecommons.org/licenses/by/2.0)]
File: Rubber_Duck_Factory.py*You can also include this class at the top of your scripts instead of the import statements if you find that more convenient.class RubberDuck():
color = 'yellow'
USAGE:File: makeOne.pyimport Rubber_Duck_FactoryOneDucky = Rubber_Duck_Factory.RubberDuck()
print(OneDucky.color)
# yellow
* Not to be confused with the factory method pattern, that's related but advanced stuff not covered here.

Make many

import Rubber_Duck_Factory# A dictionary to store our ducks:
_ducks = {}
# create 7 ducks and add them to the dictionary:
for i in range(7):
_ducks[i] = Rubber_Duck_Factory.RubberDuck()
print(_ducks)# {0: <Rubber_Duck_Factory.RubberDuck object at 0x106d9f080>, 1: <Rubber_Duck_Factory.RubberDuck object at 0x10725c780>, 2: <Rubber_Duck_Factory.RubberDuck object at 0x10725c748>, 3: <Rubber_Duck_Factory.RubberDuck object at 0x10725c940>, 4: <Rubber_Duck_Factory.RubberDuck object at 0x10725c828>, 5: <Rubber_Duck_Factory.RubberDuck object at 0x10725ca58>, 6: <Rubber_Duck_Factory.RubberDuck object at 0x10725cac8>}# Get the color of the 5th duck, we start counting from zero:
print(_ducks[4].color)
# yellow

Make each one special

import Rubber_Duck_Factory
import random
_ducks = {}
# Colors list :
COLORS = ['blue','red','purple','orange']
# create 5 ducks:
for i in range(5):
_ducks[i] = Rubber_Duck_Factory.RubberDuck()
# Assign each duck a random color
_ducks[i].color = random.choice(COLORS)
# Go over the _ducks dictionary:
for i in range(5):
print('ducky: '+ str(i+1) + ' color is :' + _ducks[i].color)
ducky: 1 color is :red
ducky: 2 color is :blue
ducky: 3 color is :blue
ducky: 4 color is :orange
ducky: 5 color is :purple
_ducks[3].color = 'burberry'

More Object Oriented

File: Rubber_Duck_Factory.pyimport randomCOLORS = ['Red', 'Blue', 'Yellow', ‘Grey']
NAMES = ['Peter', ’Susan', 'Oswald', 'Maria', 'James']
class RubberDuck():
def __init__(self):
self.color = random.choice(COLORS)
self.name = random.choice(NAMES)
import Rubber_Duck_Factory_ducks = {}# create 6 Ducks
for i in range(6):
_ducks[i] = Rubber_Duck_Factory.RubberDuck()
# Go over the _ducks dictionary:
for i in range(6):
print( _ducks[i].color + ' Ducky\'s Name is ' + _ducks[i].name)
OUTPUT:Blue Ducky's Name is Oswald
Grey Ducky's Name is James
Yellow Ducky's Name is Maria
Red Ducky's Name is Oswald
Blue Ducky's Name is Susan
Grey Ducky's Name is Peter

Even more OOP (Object Oriented Programming)

File: Rubber_Duck_Factory.pyimport randomCOLORS = ['Red', 'Blue', 'Yellow', 'Pink', 'Grey']
NAMES = ['Peter', 'Susan', 'Oswald', 'Maria', 'James']
class RubberDuck():
def __init__(self):
self.color = random.choice(COLORS)
self.name = random.choice(NAMES)
def goRouge(self):
self.color = 'Pirate'
self.name = 'Captain Morgan'
# Tell duck #3 to do something
_ducks[2].goRouge()
print( _ducks[2].color + ' Ducky\'s Name is ' + _ducks[2].name)OUTPUT:
Pirate Ducky's Name is Captain Morgan
Here to commandeer your bathtub ?

Small Recap - Pattern:

Object Definitions on the left and Object Instances on the right.

Iteration

Iterate and change all the elements of our _ducks dictionary after creation:for i in _ducks:
_ducks[i].color = 'money'
Another way through key/values:for i, duck in _ducks.items():
duck.color = ‘rainbow'

Selecting ,Removing, Adding.

# Turn Grey Ducks into White ones:for i in _ducks:
if _ducks[i].color == 'Grey':
_ducks[i].color = 'White'
# Note that == tests equality and = assigns.
for i in list(_ducks):
if _ducks[i].color == 'White' and _ducks[i].name == 'James':
del _ducks[i]
This bit while seemingly simple has one gotcha, we are using a list before our dictionary, this is because we are iterating and changing the iteration elements, so we need to make a copy, read more about it here: How to avoid “RuntimeError: dictionary changed size during iteration” error?
_ducks[1] = Rubber_Duck_Factory.RubberDuck()
_ducks[1].color = 'Tan'
_ducks[1].name = 'James'
⚠️ Note that we need to provide the index or slot _ducks[1], which requires us to keep track of what position or key in our dictionary James used to occupy, but we could also have added James somewhere else _ducks[111], it also doesn’t need to be a number, we could for instance have done _ducks[‘returningDuck’], the dictionary just doesn't care, next sections deal with this.
#Try to create 5 ducks THIS DOESN'T WORK:for i in range(5):
tempDuck = Rubber_Duck_Factory.RubberDuck()
_ducks[tempDuck.name] = tempDuck
# _ducks{} Dictionary :# {'Susan': <Rubber_Duck_Factory.RubberDuck object at 0x1041c5be0>, 'Oswald': <Rubber_Duck_Factory.RubberDuck object at 0x103d07080>, 'Maria': <Rubber_Duck_Factory.RubberDuck object at 0x103ce2ef0>}
THIS SOMETIMES WORKS:for i in range(5):
tempDuck = Rubber_Duck_Factory.RubberDuck()
_ducks[id(tempDuck)] = tempDuck
# _ducks{} Dictionary :{4485467888: <Rubber_Duck_Factory.RubberDuck object at 0x10b5acef0>, 4485615744: <Rubber_Duck_Factory.RubberDuck object at 0x10b5d1080>, 4490585984: <Rubber_Duck_Factory.RubberDuck object at 0x10ba8e780>, 4490587104: <Rubber_Duck_Factory.RubberDuck object at 0x10ba8ebe0>, 4490587440: <Rubber_Duck_Factory.RubberDuck object at 0x10ba8ed30>, 4490587496: <Rubber_Duck_Factory.RubberDuck object at 0x10ba8ed68>, 4490587608: <Rubber_Duck_Factory.RubberDuck object at 0x10ba8edd8>}Note: 0x10b5acef0 is hex for 4485467888

Lists vs Dictionaries for Storing Objects

Don't feel bad if halfway through your project your data structure turns out to be the wrong one, this happens more often than we'd like to admit and is usually caused by us learning about the domain and/or language as we write, so it's part of the process, rectifying the situation is usually less of an issue if you use objects.
import Rubber_Duck_Factory# Now a List:
_ducks = []
# create 6 Ducks
for i in range(6):
_ducks.append(Rubber_Duck_Factory.RubberDuck())
# Iterate :for i, duckObject in enumerate(_ducks):
print (i, ",",duckObject)
# OUTPUT:# 0 , <Rubber_Duck_Factory.RubberDuck object at 0x0000022FE7CA1308>
# 1 , <Rubber_Duck_Factory.RubberDuck object at 0x0000022FE7CA6208>
# 2 , <Rubber_Duck_Factory.RubberDuck object at 0x0000022FE7CA6448>
# 3 , <Rubber_Duck_Factory.RubberDuck object at 0x0000022FE7CA6948>
# 4 , <Rubber_Duck_Factory.RubberDuck object at 0x0000022FE7CA6BC8>
# 5 , <Rubber_Duck_Factory.RubberDuck object at 0x0000022FE7CA6CC8>
for duck in _ducks:
print(duck.name + ' the ' + duck.color + ' ducky')
# OUTPUT:
# James the Yellow ducky
# Maria the Blue ducky
# Susan the Red ducky
# Oswald the Pink ducky
# Peter the Grey ducky
# James the Blue ducky
# Change all:
for duck in _ducks:
duck.color ='black'
# OUTPUT:
# James the black ducky
# Maria the black ducky
# Susan the black ducky
# Oswald the black ducky
# Peter the black ducky
# James the black ducky
# Select and Remove:
for duck in _ducks:
if duck.name == 'James' and duck.color == 'black':
_ducks.remove(duck)
# OUTPUT:
# Maria the black ducky
# Susan the black ducky
# Oswald the black ducky
# Peter the black ducky
Our ducks are numbered now.
insert a new duck at the third slot.
_ducks.insert(2, Rubber_Duck_Factory.RubberDuck())
Note that the ducks reorder themselves after insertion.
What to use ? Lists for when you need to keep objects ordered,dictionaries for when key,value selection makes more sense, realistically you will be using both (or a mix )most of the time.

Conclusions

Where to go next ? - List/Dict Comprehension: For complex selection and modification - Object Inheritance and Patterns For more varied Data Structures and efficient creation of many things ( ex. factory pattern ). - Itertools, collections, tuples More ways to iterate and places to put your objects.  

AI, Software Developer, Designer : www.k3no.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store