Python Fundamentals#
This is where we start writing actual Python. Before we can analyze climate data, we need the language’s building blocks: the numbers and text we compute with, the lists and dictionaries we store data in, and the loops and conditionals that let us process it. Everything later in the course — NumPy arrays, pandas DataFrames, xarray datasets — is built on these foundations, so time spent here pays off everywhere.
This material is adapted from the official Python tutorial (Copyright 2001–2024, Python Software Foundation), used under the Python License.
Working through this notebook
This page is a Jupyter notebook. Download it using the ⬇ button in the top-right of the page, open it in your environment (JupyterLab on LEAP or Colab), and step through the cells. When you reach a Try it admonition, experiment in your own cells before moving on.
In-class assignment — 10 points
The “Try it” exercises in this notebook are part of your in-class assignment for this section. Complete them in your own copy of the notebook, push it to your week folder, and post the notebook link on the matching Courseworks assignment. (One 10-point assignment covers all the lecture notebooks in this section.)
Invoking Python#
There are three main ways to use Python.
By running a Python file, e.g.
python myscript.pyThrough an interactive console (Python interpreter or iPython shell)
In an interactive notebook (e.g. Jupyter)
In this course, we will mostly be interacting with Python via Jupyter notebooks.
Basic Variables: Numbers and Strings#
In Python you create a variable by assigning a value to a name with =. Every variable has a type — int, str, float, bool, etc. — which determines what operations you can do with it. This section covers declaring variables, checking their types, and how Python handles operations between types.
# comments are anything that comes after the "#" symbol
a = 1 # assign 1 to variable a
b = "hello" # assign "hello" to variable b
Reference: Python has a small set of reserved words (
if,def,for,class, etc.) that can’t be used as variable names, and a long list of built-in functions (len,type,range, etc.) that are always available. You don’t need to memorize either list — just be aware they exist.
# how to we see our variables?
print(a)
print(b)
print(a,b)
1
hello
1 hello
In Python, every piece of data is an object — numbers, strings, lists, even functions are all objects. Each object has a type (also called its class) that determines what you can do with it. You can add numbers, for example, but adding a number to a string raises an error, as we’ll see below.
You can check the type of any value with the built-in type() function:
print(type(a))
print(type(b))
<class 'int'>
<class 'str'>
Shortcut: in a Jupyter notebook, the value of the last line of a code cell is automatically displayed — no print() needed:
type(b)
str
# we can check for the type of an object
print(type(a) is int)
print(type(a) is str)
True
False
Every object has its own attributes (data) and methods (functions you can call on it), accessed with the variable.method syntax. In Jupyter, press <tab> after a . to see what’s available — this is called tab completion.
# this returns the method itself
b.capitalize
<function str.capitalize()>
# this calls the method
b.capitalize()
# there are lots of other methods
'Hello'
# binary operations act differently on different types of objects
c = 'World'
print(b + c)
print(a + 2)
print(a + b)
helloWorld
3
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[8], line 5
1 # binary operations act differently on different types of objects
2 c = 'World'
3 print(b + c)
4 print(a + 2)
----> 5 print(a + b)
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Try it
In a fresh code cell, declare your own variables of a few different types — a number, a string, and a boolean — and check each one’s type with type(). Try a binary operation that mixes types (like "a" + 1) to see what error you get.
Math#
Basic arithmetic and boolean logic is part of the core Python library.
# addition / subtraction
1+1-5
-3
# multiplication
5 * 10
50
# division
1/2
0.5
# that was automatically converted to a float
type(1/2)
float
# exponentiation
2**4
16
# rounding
round(9/10)
1
# built in complex number support
(1+2j) / (3-4j)
(-0.2+0.4j)
# logic
True and True
True
True and False
False
True or True
True
(not True) or (not False)
True
Try it
In a fresh code cell, try a few arithmetic operations of your own — addition, multiplication, exponentiation. Confirm with type() that 1/2 is a float but 1+1 is an int. Try a boolean expression too: what does (True and False) or True evaluate to?
Conditionals#
Conditionals let your program make decisions: do this if a condition is true, otherwise do that. Python uses if, elif (else-if), and else to express these branches. Indentation matters — Python uses it to group statements into blocks (unlike languages that use braces).
x = 100
if x > 0:
print('Positive Number')
elif x < 0:
print('Negative Number')
else:
print ('Zero!')
Positive Number
# indentation is MANDATORY
# blocks are closed by indentation level
if x > 0:
print('Positive Number')
if x >= 100:
print('Huge number!')
Positive Number
Huge number!
Try it
In a fresh code cell, write your own if / elif / else block that prints "small", "medium", or "large" based on a number you set. Change the number and re-run to make sure all three branches fire.
More Flow Control#
Beyond conditionals, the main way to repeat work in Python is with loops. A while loop runs as long as a condition is true; a for loop iterates over a sequence of items (a list, a range, the keys of a dict, etc.). The range() function generates a sequence of numbers that’s useful with for.
# a while loop
count = 0
while count < 10:
count += 1 # shorthand for: count = count + 1
print(count)
10
# use range
for i in range(5):
print(i)
0
1
2
3
4
Important point: in Python, we always count from 0!
Reference: In Jupyter, type a name followed by
?(e.g.range?) in a code cell to see the built-in help for it. Works for any function, type, or variable.
# iterate over a list we make up
for pet in ['dog', 'cat', 'fish']:
print(pet, len(pet))
dog 3
cat 3
fish 4
Try it
In a fresh code cell, write a for loop that prints the squares of the numbers 0 through 9 (one per line). Then write a while loop that does the same thing.
Lists#
A list is an ordered, mutable collection of items, written with square brackets like ['dog', 'cat', 'fish']. You can add to a list, remove from it, sort it, and access items by position. Lists are the workhorse data structure of Python — used everywhere from holding a handful of items to storing thousands of records.
l = ['dog', 'cat', 'fish']
type(l)
list
# list have lots of methods
l.sort()
l
['cat', 'dog', 'fish']
# we can convert a range to a list
r = list(range(5))
r
[0, 1, 2, 3, 4]
while r:
p = r.pop()
print('p:', p)
print('r:', r)
p: 4
r: [0, 1, 2, 3]
p: 3
r: [0, 1, 2]
p: 2
r: [0, 1]
p: 1
r: [0]
p: 0
r: []
Reference: Lists have many built-in methods —
append,extend,insert,remove,pop,clear,index,count,sort,reverse,copy. See the Python docs on lists for the full reference. The ones you’ll use most in this course areappend,sort, andpop.
# "add" two lists
x = list(range(5))
y = list(range(10,15))
z = x + y
z
[0, 1, 2, 3, 4, 10, 11, 12, 13, 14]
# access items from a list
print('first', z[0])
print('last', z[-1])
print('first 3', z[:3])
print('last 3', z[-3:])
print('middle, skipping every other item', z[5:10:2])
first 0
last 14
first 3 [0, 1, 2]
last 3 [12, 13, 14]
middle, skipping every other item [10, 12, 14]
MEMORIZE THIS SYNTAX! It is central to so much of Python and often proves confusing for users coming from other languages.
In terms of set notation, Python indexing is left inclusive, right exclusive. If you remember this, you will never go wrong.
# that means we get an error from the following
N = len(z)
z[N]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
Cell In[31], line 3
1 # that means we get an error from the following
2 N = len(z)
----> 3 z[N]
IndexError: list index out of range
# this index notation also applies to strings
name = 'Ryan Abernathey'
print(name[:4])
Ryan
# you can also test for the presence of items in a list
5 in z
False
Lists are general-purpose containers — they can hold mixed types and grow or shrink. For numerical math on many values at once, you’ll use NumPy arrays (covered later).
z[4] = 'fish'
z
[0, 1, 2, 3, 'fish', 10, 11, 12, 13, 14]
Python is full of tricks for iterating and working with lists
# a cool Python trick: list comprehension
squares = [n**2 for n in range(5)]
squares
[0, 1, 4, 9, 16]
# iterate over two lists together using zip
for item1, item2 in zip(x, y):
print('first:', item1, 'second:', item2)
first: 0 second: 10
first: 1 second: 11
first: 2 second: 12
first: 3 second: 13
first: 4 second: 14
Try it
In a fresh code cell, create a list of your own (any topic) and try a few methods — .append(...), .sort(), len(...). Then try slicing: mylist[:2], mylist[-1], mylist[::2]. Predict each result before you run it.
Other Data Structures#
We have the basic building blocks for programming now. Python has two more data structures we’ll meet often: tuples and dictionaries.
Tuples#
Tuples are similar to lists, but they are immutable — they can’t be extended or modified once created. Their main use is to pack together a small group of related values (often of different types) that travel as a unit, so other parts of your code can unpack them.
# tuples are created with parentheses, or just commas
a = ('Ryan', 33, True)
b = 'Takaya', 25, False
type(b)
tuple
# can be indexed like arrays
print(a[1]) # not the first element!
33
# and they can be unpacked
name, age, status = a
print(name, age, status)
Ryan 33 True
Try it
In a fresh code cell, create your own tuple with a few different types (e.g., a name string, an age int, and a boolean). Unpack it into three named variables and print each. Then try to modify it (e.g., t[0] = "new") — what error do you get?
Dictionaries#
This is an extremely useful data structure. It maps keys to values.
Dictionaries are unordered!
# different ways to create dictionaries
d = {'name': 'Ryan', 'age': 33}
e = dict(name='Takaya', age=25)
e
{'name': 'Takaya', 'age': 25}
# access a value
d['name']
'Ryan'
Square brackets [...] are Python for “get item” in many different contexts.
# test for the presence of a key
print('age' in d)
print('height' in e)
True
False
# try to access a non-existant key
d['height']
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[43], line 2
1 # try to access a non-existant key
----> 2 d['height']
KeyError: 'height'
# add a new key
d['height'] = (5,11) # a tuple
d
{'name': 'Ryan', 'age': 33, 'height': (5, 11)}
# keys don't have to be strings
d[99] = 'ninety nine'
d
{'name': 'Ryan', 'age': 33, 'height': (5, 11), 99: 'ninety nine'}
# iterate over keys
for k in d:
print(k, d[k])
name Ryan
age 33
height (5, 11)
99 ninety nine
# nicer way: iterate over keys and values at once
for key, val in d.items():
print(key, val)
name Ryan
age 33
height (5, 11)
99 ninety nine
Try it
In a fresh code cell, create a dict mapping a few country names to their capitals. Look up one capital. Iterate through the dict and print each key: value pair. Try looking up a country that’s not in the dict — what happens?
Recap#
You’ve now met the core building blocks of the Python language:
Variables and types — numbers, strings, and booleans, and checking a value’s type.
Math and operators — arithmetic and comparisons, and the difference between
=(assignment) and==(comparison).Control flow —
if/elif/elseto make decisions, andfor/whileloops to repeat work.Data structures — lists (ordered, mutable), tuples (ordered, fixed), and dictionaries (key→value lookups) — the containers you’ll reach for constantly.
Next we’ll package this logic into reusable functions and classes in Functions and Classes.