2.1. Basic Python
Your First Python Code
Every programming journey begins with a simple act of communication between you and the machine. In Python, that act is the print() function, one of the language’s most frequently used built-in tools.
print("Hello World")This command tells Python to display text on the screen. While this may seem trivial, print() will become one of your most important debugging tools as you progress through geospatial analysis. When you are processing pedestrian count data across hundreds of street segments, for instance, strategically placed print() statements help you verify that your code is producing the expected results at each stage of the analysis pipeline.
Adding Comments
Comments help document your code. Python supports two types:
# This is a single-line comment
'''
This is a multi-line comment
Line 1
Line 2
Line 3
'''
print('Hello World!') # Comments can also appear at the end of linesGood comments explain why you’re doing something, not just what you’re doing. Your code should be readable enough that the “what” is obvious.
Python as a Calculator
Before you analyse complex datasets, you should know that Python works as a powerful calculator out of the box. This matters because much of urban analytics involves arithmetic operations on spatial and demographic data. Whether you are computing pedestrian density (people per square metre), walkability scores, or average trip distances, mathematical operations form the foundation of every analysis.
# Addition
1 + 1 # Returns: 2
# Multiplication
5 * 7 # Returns: 35
# Exponentiation
2**3 # Returns: 8
# Modulus (remainder)
10 % 2 # Returns: 0More Mathematical Operators
The table below summarises Python’s core arithmetic operators. Pay particular attention to the distinction between true division (/) and floor division (//), as this distinction becomes important when you work with spatial binning or grid-based analyses where you need integer results.
| Operation | Operator | Example | Result |
|---|---|---|---|
| Addition | + |
5 + 3 |
8 |
| Subtraction | - |
5 - 3 |
2 |
| Multiplication | * |
5 * 3 |
15 |
| Division | / |
11 / 2 |
5.5 |
| Floor Division | // |
11 // 2 |
5 |
| Modulus | % |
11 % 2 |
1 |
| Exponentiation | ** |
2 ** 3 |
8 |
| Negation | - |
-5 |
-5 |
# True division gives decimal result
print(11 / 2) # Output: 5.5
# Floor division gives integer result (rounds down)
print(11 // 2) # Output: 5For instance, if you have 11 pedestrian sensors across 2 city zones and want to know how many full sensors each zone gets, floor division gives you 5, while the modulus operator (11 % 2 = 1) tells you one sensor remains unassigned.
Python Syntax Essentials
Understanding Python’s syntax rules early on prevents frustrating errors later. Unlike languages such as Java or C++ that use braces and semicolons, Python relies on whitespace and line breaks to structure code. This design philosophy, championed by Python’s creator Guido van Rossum, prioritises readability, which is especially valuable when collaborating on geospatial projects where code must be understood by team members from different disciplinary backgrounds.
End-of-Line Terminates Statements
In Python, the end of a line marks the end of a statement:
temperature = 5This is an assignment operation, where we create a variable named temperature and assign it the value 5.
If you need a statement to continue to the next line, use the backslash (\):
x = 1 + 2 + 3 + 4 + \
5 + 6 + 7 + 8Whitespace Within Lines
Whitespace within lines doesn’t matter for Python’s interpretation:
x=1+2
x = 1 + 2
x = 1 + 2All three lines are equivalent, but which is most readable? The second option with consistent spacing is preferred.
Indentation Matters!
This is one of Python’s most distinctive features and a common source of early frustration. Unlike many programming languages that use curly braces {} to define blocks of code, Python uses indentation. This was a deliberate design choice to enforce readable code. In practice, it means that the visual structure of your programme directly reflects its logical structure, which makes Python code easier to read and review during collaborative geospatial projects.
# Correct indentation
if temperature > 25:
print("It's hot!")
print("Stay hydrated!")
# Incorrect - will cause an error
if temperature > 25:
print("It's hot!") # IndentationError!Always use 4 spaces for indentation (most editors can convert Tab to spaces automatically). Mixing tabs and spaces will cause errors.
Round Brackets
Round brackets (or parentheses in the US context) serve three distinct purposes in Python, and recognising which role they play in any given line of code helps you read programmes fluently. First, they group mathematical operations to control the order of evaluation, just as they do in standard arithmetic. Second, they call functions, instructing Python to execute a named block of code. Third, they execute methods, which are functions that belong to a specific object. The examples below illustrate each role:
# 1. Grouping mathematical operations
2 * (3 + 4) # Returns: 14
# 2. Calling functions
print('first value:', 1)
len('Hello World')
# 3. Executing methods on objects
L = [4, 2, 3, 1]
L.sort() # Parentheses execute the sort method
print(L) # Output: [1, 2, 3, 4]Variables and Assignment
A variable stores values for later use. Think of it as a labelled box in computer memory. Variables are the mechanism through which your programme remembers information between operations. In pedestrian mobility research, you might store a walkability index score, the number of pedestrians counted at an intersection during peak hours, or the coordinates of a survey location. Without variables, every computation would be a one-off calculation with no way to build upon previous results.
weather = "Freezing"
print(weather) # Output: Freezing
temperature = 15
print(temperature) # Output: 15Variables as Pointers
Variables in Python are references (pointers) to objects in memory:
x = [1, 2, 3]
y = x # Both x and y point to the same list
# Modifying the list through x
x.append(4)
print(y) # Output: [1, 2, 3, 4] - y sees the change!
# Reassigning x
x = 'something else'
print(y) # Output: [1, 2, 3, 4] - y is unchangedThis behaviour is important when working with data structures in geospatial analysis.
Data Types
Everything Is an Object
Python is an object-oriented language, which means that every piece of data you work with is an “object” that carries both information and behaviour.
Each object has attributes (data associated with it) and methods (functions that can operate on it). This design is not merely an academic abstraction. When you work with geospatial libraries like GeoPandas in Section 2.4, every geometry object (a point, line, or polygon) will come with built-in methods such as .buffer(), .centroid, and .area that you can call directly. Understanding the object-oriented paradigm now will make those later sections far more intuitive.
x = 4
type(x) # Returns: <class 'int'>
x = 'hello'
type(x) # Returns: <class 'str'>
x = 3.14159
type(x) # Returns: <class 'float'>Basic Data Types
Python has four fundamental data types, each suited to representing different kinds of real-world information.
- Integers (
int) represent whole numbers and are ideal for counts, such as the number of pedestrians passing a sensor. - Floats (
float) handle decimal numbers and are essential for measurements like walking distances in kilometres or pollution concentrations in micrograms per cubic metre. - Strings (
str) store text, from street names to neighbourhood classifications. - Booleans (
bool) represent binary true/false values and are used for logical tests, such as whether a street segment falls within a low-emission zone.
| Type | Description | Example |
|---|---|---|
int |
Whole numbers | 4, -17, 0 |
float |
Decimal numbers | 3.1415, -2.5 |
str |
Text strings | 'Hello', "Auckland" |
bool |
True/False values | True, False |
Working with Strings
Strings represent text data and are ubiquitous in geospatial work. Street names, suburb classifications, CRS identifiers, and file paths are all strings. Knowing how to manipulate them, whether through concatenation, case conversion, or splitting, is essential for data cleaning tasks that precede any spatial analysis.
city = "Auckland"
print(city) # Output: Auckland
# Length of string
len(city) # Returns: 8
# String concatenation
greeting = "Hello, " + city
print(greeting) # Output: Hello, Auckland
# String repetition
print(city * 3) # Output: AucklandAucklandAuckland
# Case transformations
print(city.upper()) # Output: AUCKLAND
print(city.lower()) # Output: aucklandStrings have many useful methods. Access them with dot notation:
text = " Hello World "
text.strip() # Remove whitespace: "Hello World"
text.replace("World", "Python") # Replace text
text.split() # Split into list: ["Hello", "World"]Working with Numbers
my_int = 2
my_float = 24.3
# Mixing int and float gives float
my_int + my_float # Returns: 26.3 (float)
# Division always returns float
10 / 5 # Returns: 2.0 (not 2)
# Floor division returns int
10 // 3 # Returns: 3
# Modulus returns remainder
10 % 3 # Returns: 1
# Exponentiation
2**3 # Returns: 8Boolean Values
Booleans represent truth values and are the engine behind every decision your programme makes. When you filter a dataset to include only streets with pedestrian counts above a certain threshold, or check whether a coordinate falls within a study area boundary, you are relying on boolean logic. Understanding booleans is therefore a prerequisite for the conditional statements and data filtering operations covered later in this section and throughout the book.
x = 5
y = 4
# Comparison returns boolean
print(x > y) # Output: True
print(not(x > y)) # Output: False
print(x == y) # Output: False
print(x != y) # Output: TrueComparison Operators
Comparison operators evaluate relationships between values:
| Operator | Meaning | Example |
|---|---|---|
== |
Equal to | 5 == 5 → True |
!= |
Not equal to | 5 != 4 → True |
< |
Less than | 3 < 5 → True |
> |
Greater than | 5 > 3 → True |
<= |
Less than or equal | 5 <= 5 → True |
>= |
Greater than or equal | 5 >= 4 → True |
# Check if a number is odd
25 % 2 == 1 # Returns: True
# Check if a number is even
66 % 2 == 0 # Returns: TrueBoolean Operations
Combine boolean values with logical operators:
| Operator | Description | Example |
|---|---|---|
and |
Both must be True | True and False → False |
or |
At least one must be True | True or False → True |
not |
Inverts the value | not True → False |
x = 4
# Both conditions must be true
(x < 6) and (x > 2) # Returns: True
# At least one condition must be true
(x > 10) or (x % 2 == 0) # Returns: True
# Invert the condition
not (x < 6) # Returns: FalseLists
Lists are one of Python’s most versatile data structures and will be your workhorse throughout this book.
A list is an ordered collection that can hold multiple values, making it the natural choice for storing sequences of related data such as a series of pedestrian counts from different time intervals, a collection of street names along a walking route, or latitude-longitude pairs for survey locations. Sevtsuk and Kalvo (2024) demonstrate how lists of origin and destination points feed into network-based pedestrian trip models, underscoring the practical importance of this data structure in urban mobility research.
# Create a list
cities = ["Auckland", "Wellington", "Christchurch"]
# Access elements (zero-indexed)
cities[0] # Returns: "Auckland"
cities[1] # Returns: "Wellington"
cities[-1] # Returns: "Christchurch" (last item)
# List length
len(cities) # Returns: 3List Operations
# Create a list of numbers
numbers = [1, 2, 3, 4, 5]
# Slicing: get a subset
numbers[1:3] # Returns: [2, 3]
numbers[:3] # Returns: [1, 2, 3] (first three)
numbers[2:] # Returns: [3, 4, 5] (from index 2 onwards)
# Modify a list
numbers[0] = 10
print(numbers) # Output: [10, 2, 3, 4, 5]
# Append an item
numbers.append(6)
print(numbers) # Output: [10, 2, 3, 4, 5, 6]More List Methods
western_line = ["Britomart", "Parnell", "Newmarket", "Grafton"]
# Add an item to the end
western_line.append("Mt Eden")
# Extend with another list
more_stations = ["Kingsland", "Morningside", "Baldwin Ave"]
western_line.extend(more_stations)
# Insert at specific position
western_line.insert(1, "Strand")
# Remove an item
western_line.remove("Strand")
# Sort the list
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
numbers.sort()
print(numbers) # Output: [1, 1, 2, 3, 4, 5, 6, 9]Lists can contain: - Different data types: [1, "hello", 3.14, True] - Other lists: [[1, 2], [3, 4], [5, 6]] - Any Python objects
For Loops
Loops are what transform Python from a simple calculator into a powerful analytical tool. A for loop allows you to apply the same operation to every item in a collection, eliminating the need to write repetitive code for each data point. This capability is essential in urban analytics, where datasets routinely contain thousands or millions of records.
Consider a practical scenario: if you have pedestrian count data from 500 street segments across Auckland, a for loop lets you calculate the walking volume per metre of pavement for every segment in a single block of code, rather than writing 500 separate calculations. As Lovelace et al. (2019) note in Geocomputation with R (whose principles translate directly to Python), automation through iteration is a cornerstone of reproducible geographic analysis.
Basic For Loop Syntax
for variable in collection:
do_something_with_variableThere are three syntax rules to remember. The loop statement must end with a colon (:), the code inside the loop must be indented by 4 spaces, and no special end statement is needed because Python uses the return to normal indentation to mark the end of the loop body.
Example: Iterating Through a List
western_line = ["Britomart", "Parnell", "Newmarket", "Grafton",
"Mt Eden", "Kingsland", "Morningside", "Baldwin Ave"]
for station in western_line:
print(station)Output:
Britomart
Parnell
Newmarket
Grafton
Mt Eden
Kingsland
Morningside
Baldwin Ave
Using Range
The range() function generates sequences of numbers:
# Print numbers 0 to 4
for value in range(5):
print(value)
# Output:
# 0
# 1
# 2
# 3
# 4Working with Multiple Lists
cities = ["Helsinki", "Stockholm", "Oslo", "Reykjavik", "Copenhagen"]
countries = ["Finland", "Sweden", "Norway", "Iceland", "Denmark"]
# Iterate using indices
for i in range(len(cities)):
print(cities[i], "is the capital of", countries[i])
# Output:
# Helsinki is the capital of Finland
# Stockholm is the capital of Sweden
# Oslo is the capital of Norway
# Reykjavik is the capital of Iceland
# Copenhagen is the capital of DenmarkIn geospatial analysis, loops are the mechanism that makes batch processing possible. You will use them to read and process multiple data files (e.g. pedestrian count CSVs from different months), to calculate summary statistics for each region or street segment in a dataset, to generate maps for different time periods or scenarios, and to apply coordinate transformations or spatial operations to every feature in a GeoDataFrame. The MIT 11.024x course on pedestrian mobility in cities, for example, uses iterative analysis over street networks to compute accessibility indices for every node in a city’s pedestrian graph.
Conditional Statements
Conditional statements give your programme the ability to make decisions, executing different blocks of code depending on whether a condition is true or false. This is how you translate domain knowledge into computational logic. For example, in pedestrian exposure research, you might classify street segments as “high exposure” or “low exposure” based on whether pollutant concentrations exceed a World Health Organisation guideline threshold. Without conditionals, your programme would treat every data point identically, which is rarely what real-world analysis requires.
If-Else Structure
temperature = 17
if temperature > 25:
print("It's hot!")
else:
print("It's not hot!")
# Output: It's not hot!If Without Else
Sometimes you only need action when a condition is true:
temperature = 17
if temperature > 25:
print(temperature, "is greater than 25")
# No output because condition is FalseIf-Elif-Else
Use elif (else if) for multiple conditions:
temperature = -3
if temperature > 0:
print(temperature, "degrees celsius is above freezing")
elif temperature == 0:
print(temperature, "degrees celsius is at the freezing point")
else:
print(temperature, "degrees celsius is below freezing")
# Output: -3 degrees celsius is below freezingPython checks conditions in order and executes the first true block.
Comparison with Strings
weather = "rain"
if weather == "rain":
print("Wear a raincoat!")
else:
print("No raincoat needed.")
# Output: Wear a raincoat!Combining Conditions
Use and and or to create complex conditions:
weather = "rain"
wind_speed = 14
comfort_limit = 10
# Multiple conditions with 'or'
if (weather == "rain") or (wind_speed >= comfort_limit):
print("Just stay at home")
else:
print("Go out and enjoy the weather!")
# Output: Just stay at homeCombining Loops and Conditionals
Combining loops with conditionals is arguably the most powerful pattern in introductory programming, because it allows you to iterate through an entire dataset while applying different logic to different records. This pattern underpins virtually all data processing pipelines in urban analytics. For instance, when Sevtsuk’s Urban Network Analysis framework computes pedestrian trip distributions across a city’s street network, it iterates over each network edge (a loop) and evaluates whether that edge meets certain accessibility or connectivity criteria (a conditional) before assigning trip volumes.
temperatures = [0, 12, 17, 28, 30]
# Check each temperature
for temperature in temperatures:
if temperature > 25:
print(temperature, "is hot")
else:
print(temperature, "is not hot")
# Output:
# 0 is not hot
# 12 is not hot
# 17 is not hot
# 28 is hot
# 30 is hotPractical Example: Processing Sensor Data
sensor_readings = [15.2, 23.1, 45.7, 12.8, 38.9]
threshold = 30.0
high_readings = []
for reading in sensor_readings:
if reading > threshold:
high_readings.append(reading)
print(f"Alert: Reading {reading} exceeds threshold!")
print(f"\nTotal high readings: {len(high_readings)}")Methods and Dot Notation
Objects in Python have methods—functions that belong to the object:
L = [1, 2, 3]
# Append method adds an item
L.append(100)
print(L) # Output: [1, 2, 3, 100]
# Check if a float is an integer
x = 4.5
x.is_integer() # Returns: False
x = 4.0
x.is_integer() # Returns: TrueThe dot (.) connects the object to its method: object.method()
Getting Help
You do not need to memorise every function or method in Python. Professional developers rely heavily on documentation and community resources, and you should too. The official Python documentation at https://www.python.org/doc is comprehensive and well-organised. Within Python itself, you can use help(function_name) to access built-in documentation, or print(function_name.__doc__) to read a function’s docstring directly.
Beyond the official documentation, Stack Overflow is an invaluable resource for searching error messages and finding solutions that others have encountered. Real Python offers well-structured tutorials, and the documentation for specific packages (pandas, geopandas, matplotlib) is often the fastest route to understanding how a particular function works.
AI tools such as ChatGPT and Gemini can help explain concepts and generate code snippets. However, it is essential that you understand the code they produce rather than blindly copying it into your projects. You will need that understanding for debugging, adapting code to new datasets, and explaining your methodology in academic or professional contexts.
While AI tools accelerate learning, treat their output as a starting point rather than a finished product. Verify that generated code follows the conventions used in your project, handles edge cases in your data, and produces results you can explain and defend. This is especially important in research settings where reproducibility and methodological transparency are non-negotiable.
Practical Exercise: Auckland Transport
Let’s combine everything we’ve learned:
# Auckland transport data
stations = ["Britomart", "Newmarket", "Mt Eden", "Henderson"]
daily_passengers = [15000, 8500, 6200, 4100]
target = 7000
for i in range(len(stations)):
station = stations[i]
passengers = daily_passengers[i]
print(f"\n{station} Station:")
print(f" Daily passengers: {passengers:,}")
if passengers >= 10000:
print(" Status: High volume station ✓")
elif passengers >= ______: # <-- Quiz 1
print(" Status: Medium volume station ✓")
else:
shortfall = target - passengers
print(f" ✗ Below target by {shortfall:,} passengers")
print(" Status: Low volume station")Given target = 7000, which ordering works correctly?
- A.
if passengers >= target→elif passengers >= 10000 - B.
if passengers >= 10000→elif passengers >= target
- C.
if passengers >= 10000→elif passengers <= target - D.
if passengers <= target→elif passengers >= 10000
Summary
This section has covered the foundational building blocks of Python programming. You have learned how Python’s syntax, particularly its use of indentation to define code structure, enforces readable and maintainable code. You have worked with the four basic data types (integers, floats, strings, and booleans) and seen how each maps to real-world data you will encounter in geospatial analysis, from pedestrian counts to street names to logical classification criteria. You have explored how variables store and reference data in memory, and why understanding Python’s reference-based variable model matters when working with mutable data structures. Through lists, for loops, and conditional statements, you have gained the ability to store collections of data, process them iteratively, and apply decision logic to each element. Combining these concepts, as demonstrated in the Auckland transport exercise, gives you the basic analytical capability to process real urban datasets.
These fundamentals are not merely academic prerequisites. They form the computational substrate upon which all subsequent geospatial analysis in this book is built. The DataFrames you will meet in Section 2.2, the visualisations in Section 2.3, and the spatial operations in Section 2.4 all rely on the patterns introduced here.
Key Takeaways
The six concepts you should take away from this section are as follows.
- Indentation matters in Python because it defines code structure, not merely aesthetics.
- Variables are references (pointers) to objects in memory, which has implications for how data is shared and modified.
- Lists are mutable ordered collections that serve as the foundation for handling sequences of spatial or temporal data.
- For loops enable you to iterate through collections efficiently, which is essential for batch processing in geospatial workflows.
- Conditional statements allow your code to make decisions based on data values, translating domain knowledge into computational logic.
- Combining loops with conditionals is the pattern you will use most frequently when processing and classifying real-world urban datasets.
Next Steps
Now that you understand Python basics, you’re ready to work with tabular data in the following section Dataframes with Pandas, where you’ll learn to use pandas for data manipulation.