Programs make decisions and repeat work. In GIS that means labelling each feature by a rule, and doing it for every row. This part covers both.
What are conditions and loops?
A condition is a question with a yes or no answer, written with comparisons such as >, <, == (equal) and != (not equal). An if statement runs a block of code only when the answer is yes. A loop runs a block again and again.
Python marks a block by indentation, normally four spaces. The line before the block ends with a colon. Indentation is part of the language, so keep it consistent.
1. if, elif and else
Classify a city by population:
population = 8443675
# Python checks the conditions from the top and runs ONLY the first one that is true.
# Notice the colon at the end of each line and the indented line below it. The indent matters.
if population >= 5_000_000: # underscores in a number are only for reading, like commas
size = "metro"
elif population >= 1_000_000: # elif = "otherwise, if..."
size = "large"
elif population >= 100_000:
size = "medium"
else: # else = "none of the above"
size = "small"
print(size)
metro
Python checks the tests from the top and runs the first block whose test is true, then skips the rest. The else block runs when nothing matched. Underscores in a number such as 5_000_000 are only for readability.
Combine tests with and, or and not:
lat, lon = 12.9716, 77.5946 # two variables set in one line
# A comparison gives True or False. "and" is True only when BOTH sides are True.
valid = (-90 <= lat <= 90) and (-180 <= lon <= 180) # are these real coordinates on Earth?
in_india = (6 <= lat <= 37) and (68 <= lon <= 98) # do they fall inside a rough box around India?
print(valid, in_india)
True True
The India test is a rough bounding box, good enough to catch swapped or missing coordinates, but not a real boundary.
2. for loops
A for loop takes the items of a collection one at a time.
cities = ["Bengaluru", "Mysuru", "Chennai"]
# A for loop repeats the indented lines once for each item in the list.
# "city" holds the current item: first Bengaluru, then Mysuru, then Chennai.
for city in cities:
print(city.upper())
BENGALURU
MYSURU
CHENNAI
The variable city holds one name per round. Everything indented under for runs each time.
Loop and calculate:
populations = {"Bengaluru": 8443675, "Mysuru": 920550, "Chennai": 4646732}
total = 0 # start the running total at zero
# .items() gives each key and its value together, so the loop can use both
for city, pop in populations.items():
total = total + pop # add this city's population to the total
print(city, pop)
print("Total:", total) # not indented, so it runs once, after the loop
Bengaluru 8443675
Mysuru 920550
Chennai 4646732
Total: 14010957
total starts at 0 before the loop, and each round adds one population to it. This "start, then update in a loop" pattern is very common. Python also has sum(populations.values()), which gives the same answer.
Useful helpers:
# range(3) gives 0, 1, 2. Handy when you just need to repeat something or number things.
for i in range(3):
print("ID", i)
# enumerate adds a counter. start=1 makes it count from 1 instead of 0.
for number, city in enumerate(cities, start=1):
print(number, city)
# zip walks through several lists at the same time, pairing the 1st with the 1st, 2nd with 2nd...
lats = [12.97, 12.30, 13.08]
lons = [77.59, 76.64, 80.27]
for city, lat, lon in zip(cities, lats, lons):
print(city, lat, lon)
ID 0
ID 1
ID 2
1 Bengaluru
2 Mysuru
3 Chennai
Bengaluru 12.97 77.59
Mysuru 12.3 76.64
Chennai 13.08 80.27
range(3) gives 0, 1, 2 and is handy for making IDs. enumerate adds a counter, and zip walks several lists together.
3. Loops with a decision inside
Put an if inside a for to process only some records, or to count things.
# A list of rows, where each row is a dictionary (a set of labelled values).
# The "Nowhere" row has a latitude of 120, which cannot exist.
places = [
{"city": "Bengaluru", "population": 8443675, "lat": 12.97, "lon": 77.59},
{"city": "Mysuru", "population": 920550, "lat": 12.30, "lon": 76.64},
{"city": "Nowhere", "population": 5000, "lat": 120.0, "lon": 77.0},
{"city": "Chennai", "population": 4646732, "lat": 13.08, "lon": 80.27},
]
good = [] # two empty lists, to be filled below
bad = []
# Loop + if: check every row and sort it into the right list
for row in places:
if -90 <= row["lat"] <= 90 and -180 <= row["lon"] <= 180:
good.append(row["city"]) # append adds one item to the end of a list
else:
bad.append(row["city"])
print("valid:", good)
print("invalid:", bad)
valid: ['Bengaluru', 'Mysuru', 'Chennai']
invalid: ['Nowhere']
Two lists start empty, and each record goes into one of them. Splitting data into valid and invalid is the first step of most cleaning scripts. continue skips to the next item and break leaves the loop early:
# continue means "skip the rest of this round and go straight to the next row"
for row in places:
if row["population"] < 10000:
continue # tiny places are skipped, so the print below does not run for them
print(row["city"], "has enough people")
Bengaluru has enough people
Mysuru has enough people
Chennai has enough people
4. while loops
A while loop repeats as long as its condition stays true. Use it when you do not know in advance how many rounds are needed.
# A while loop keeps repeating as long as its condition stays True.
buffer_km = 1
while buffer_km <= 8:
print("buffer", buffer_km, "km")
buffer_km = buffer_km * 2 # double it each time: 1, 2, 4, 8. Without this line the loop would never stop.
buffer 1 km
buffer 2 km
buffer 4 km
buffer 8 km
The loop doubles the distance each round and stops once it passes 8. Something inside the loop must change the condition, or the loop never ends. If a program seems frozen, press Ctrl+C to stop it.
A safe pattern is to process a queue until it is empty or a bad value turns up:
queue = ["12.97", "77.59", "abc", "13.08"]
while queue: # an empty list counts as False, so this runs until the list is empty
item = queue.pop(0) # take the first item out of the list
# remove the dot, then check that only digits are left; if not, it is not a number
if not item.replace(".", "").isdigit():
print("stopping at bad value:", item)
break # break leaves the loop immediately
print("ok", float(item))
ok 12.97
ok 77.59
stopping at bad value: abc
while queue is true as long as the list has items. pop(0) removes and returns the first one. Prefer for when you have a collection to walk through, and while when you wait for a condition.
5. List comprehensions
A list comprehension builds a new list from an old one in one line.
names = [" bengaluru", "MYSURU ", "chennai"]
# A list comprehension is a loop written in one line: [what to do for each item for item in list]
clean = [n.strip().title() for n in names]
print(clean)
# Add "if ..." at the end to keep only some items
pops = [8443675, 920550, 4646732]
big = [p for p in pops if p > 1_000_000]
print(big)
['Bengaluru', 'Mysuru', 'Chennai']
[8443675, 4646732]
Read the first one as "for every n in names, give n.strip().title()". The if at the end filters. The same code as a normal loop is longer, which is why comprehensions are popular:
# The same cleaning as a normal loop. Both versions do exactly the same thing; use whichever you find clearer.
clean = []
for n in names:
clean.append(n.strip().title())
A dictionary comprehension builds a dictionary the same way:
# A dictionary comprehension builds a lookup table: city name -> population
lookup = {city: pop for city, pop in zip(clean, pops)}
print(lookup)
{'Bengaluru': 8443675, 'Mysuru': 920550, 'Chennai': 4646732}
Use a comprehension for simple transformations. If you need several steps or an explanation, a normal loop is easier to read.
Run this part as a notebook
The code on this page is also a Jupyter notebook. It has the theory in text cells, then the code, then guided practice, an independent assignment and hidden solutions, so you can try each task before you look. Download the Part 3 notebook, open it in JupyterLab and run the cells from top to bottom. Part 1 shows how to install and start Jupyter.
Practice
- Write a classification for road length: under 1 km short, 1 to 10 km medium, above that long.
- Loop over a list of ten latitudes and print only those between 8 and 37 (India).
- Use
enumerateto print a numbered list of five cities. - Rewrite your latitude filter as a list comprehension.
Common mistakes
- Forgetting the colon at the end of
if,fororwhile. - Wrong indentation, which gives an
IndentationErroror runs code at the wrong time. - Writing
=inside a condition instead of==. - A
whileloop that never changes its condition. - Changing a list while looping over it.
- Putting the most general test first in an
if/elifchain, so the specific ones never run.
Key takeaways
Next: Functions and errors.

