Introduction¶
Variables and Data Types¶
Python code involves using and reasoning about different types of values, or data. E.g., 42
is an integer, 3.14
is a real number, and "Python"
is a string.
A variable is a name that refers to a value. In Python, we can use any word as a variable name as long as it starts with a letter or an underscore. However, variable names should not be a reserved word in Python such as for
, if
, class
, type
, print
, etc. as these words encode special functionality in Python.
See the Python 3 documentation for a summary of the standard built-in Python datatypes.
English name |
Type name |
Description |
Example |
---|---|---|---|
integer |
|
positive/negative whole numbers |
|
floating point number |
|
real number in decimal form |
|
boolean |
|
true or false |
|
string |
|
text |
|
list |
|
an ordered collection of objects |
|
tuple |
|
an ordered collection of objects |
|
dictionary |
|
mapping of key-value pairs |
|
none |
|
represents no value |
|
We can determine the type of an object in Python using type()
. We can print the value of the object using print()
.
x = 42
type(x)
int
print(x)
42
Note
In Jupyter, the last line of a cell will automatically be printed to screen so we don’t actually need to explicitly call print()
.
Arithmetic Operators¶
Below is a table of the syntax for common arithmetic operations in Python:
Operator |
Description |
---|---|
|
addition |
|
subtraction |
|
multiplication |
|
division |
|
exponentiation |
|
floor division |
|
modulo |
1 + 2 + 3 # add
6
2 * 12.5 # multiply
25.0
2 ** 5 # exponent
32
10 / 5 # division
2.0
Warning
Division may change int
to float
.
x = 2
type(x)
int
y = x / x
type(y)
float
25 // 2 # "floor division" - always rounds down
12
Note that the //
always results in an integer
type(25 // 2)
int
25 % 2 # the remainder when 25 is divided by 2
1
Strings¶
Strings are either enclosed in single quotes or double quotes:
single quotes, e.g.,
'Philosophy'
double quotes, e.g.,
"Economics"
There is no difference between the two ways of writing a string. In fact, there one can also use a three quotes to express a string (this is typically used for writing long strings):
"""This is a long strong"""
.'''This is another long strong'''
.
course = "PHPE 409"
type(course)
str
Python 3 has a very convenient way to build strings from variables using so-called f-strings (formatted strings, see https://www.digitalocean.com/community/tutorials/how-to-use-f-strings-to-create-strings-in-python-3 for an overview).
course_name = 'PHPE'
course_num = 409
print(f"{course_name} {course_num}")
PHPE 409
A second way to build strings is to use `+’.
'Hello' + ' ' + 'World'
'Hello World'
Note that it is an error to try to add a string and a numeric data types
course_name + ' ' + course_num # produces an error
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-18-5653dee2ca0d> in <module>
----> 1 course_name + ' ' + course_num # produces an error
TypeError: can only concatenate str (not "int") to str
course_name + ' ' + str(course_num) # convert course_num to a string
'PHPE 409'
Boolean¶
The bool
type has two values: True
and False
.
t = True
t
True
type(t)
bool
f = False
f
False
type(f)
bool
Comparison Operators¶
We can compare objects using comparison operators, and we’ll get back a Boolean result:
Operator |
Description |
---|---|
|
is |
|
is |
|
is |
|
is |
|
is |
|
is |
|
is |
1 < 2
True
2 != "2"
True
x= 2
y = 4 / 2
x == y # the values of x and y are the same
True
x is y # but x and y are not the same object (x is an int and y is a float)
False
Boolean Operators¶
Python includes the standard Boolean operators:
Operator |
Description |
---|---|
|
True when |
|
True when at least one of |
|
True when |
True and True
True
True and False
False
True or False
True
False or False
False
not True
False
not False
True
Lists, Tuples and Sets¶
Lists, tuples and sets can be sued to store multiple things (“elements”) in a single object.
list_example = [1, 2.0, 'three']
list_example
[1, 2.0, 'three']
type(list_example)
list
A list can contain any data type, even other lists.
list_example2 = [1, 2.0, [3, 4], None, True]
list_example2
[1, 2.0, [3, 4], None, True]
The values inside a list can be accessed using square bracket syntax. Note that the first element of the list is in position 0.
list_example2[0] # first element
1
list_example2[2] # 3rd element
[3, 4]
list_example2[-1] # the last element (same as list_example[4])
True
Use the colon :
to access a sub-sequence (this is called “slicing”).
list_example2[1:3] # return item 1 and 2
[2.0, [3, 4]]
A tuple
is the same as a list except that it is immutable. This means that tuples cannot be changed.
a_list = [1,2,3] # a list
a_tuple = (1,2,3) # a list
print(f"The 2nd element of a_list is {a_list[1]}")
a_list[1] = "new value"
print(f"The 2nd element of a_list is now {a_tuple[1]}")
The 2nd element of a_list is 2
The 2nd element of a_list is now 2
a_tuple[1] = "new value" # produces an error
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-46-cd0c5c39dfcf> in <module>
----> 1 a_tuple[1] = "new value" # produces an error
TypeError: 'tuple' object does not support item assignment
Three useful builtin methods that apply to lists are:
len
: return the lenght of a list,append
: append elements to the end of a listjoin
: join the elements of a list to form a string
a_list = ['this', 'is', 'a', 'list']
len(a_list)
4
a_list.append("of strings")
a_list
['this', 'is', 'a', 'list', 'of strings']
"_".join(a_list) # join the elements of a list
'this_is_a_list_of strings'
More information about the available list methods is found here: https://docs.python.org/3/tutorial/datastructures.html#more-on-lists.
Sets¶
Another built-in Python data type is the set
. This is an un-ordered list of unique items.
s = {2, 3, 5, 11, 11} # sets are defined using curly braces
s
{2, 3, 5, 11}
{1, 2, 3} == {3, 2, 1, 1}
True
[1, 2, 3] == [3, 2, 1]
False
Sets are a convenient way to remove multiple copies of an element from a list
a_list = [1, 1, 2, 3, 4, 5, 5, 6, 7, 7, 7]
list(set(a_list)) # remove multiple copies of elements
[1, 2, 3, 4, 5, 6, 7]
Dictionaries¶
A dictionary is a mapping between key-values pairs and is defined with curly-brackets:
agent = {
"name": "Eric",
"id": 1234,
"some_attribute": (1, 2, 3),
}
We can access a specific field of a dictionary with square brackets:
agent["name"]
'Eric'
agent["some_attribute"]
(1, 2, 3)
Dictionaries are mutable, so they can be editted:
agent["some_attribute"] = 42
agent
{'name': 'Eric', 'id': 1234, 'some_attribute': 42}
New key-value pairs can be added to a dictionary:
agent['another_attribute'] = 1.0
agent
{'name': 'Eric', 'id': 1234, 'some_attribute': 42, 'another_attribute': 1.0}
A dictionary key can be any immutable data type, even a tuple
.
agent[(1, 2, 3)] = True
agent
{'name': 'Eric',
'id': 1234,
'some_attribute': 42,
'another_attribute': 1.0,
(1, 2, 3): True}
You get an error if you try to access a key that doesn’t exist:
agent["not-here"] # produces error
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-61-ac6cba46c48b> in <module>
----> 1 agent["not-here"] # produces error
KeyError: 'not-here'
The following methods are helpful when reasoning about dictionaries:
agent.keys() # the keys of the dictionary
dict_keys(['name', 'id', 'some_attribute', 'another_attribute', (1, 2, 3)])
agent.values() # the values of the dictionary
dict_values(['Eric', 1234, 42, 1.0, True])
agent.items() # the key,value pairs of the dictionary
dict_items([('name', 'Eric'), ('id', 1234), ('some_attribute', 42), ('another_attribute', 1.0), ((1, 2, 3), True)])
Note
For a nice overview of dictionaries in Python, see this article.
Conditionals¶
Conditional statements allow blocks of code to be exected depending on the value of one or more variables. The main conditional statement is an if/then statement:
The keywords are
if
,elif
andelse
The colon
:
ends each conditional expressionIndentation (by 4 empty space) defines code blocks
In an
if
statement, the first block whose conditional statement returnsTrue
is executed and the program exits theif
blockif
statements don’t necessarily needelif
orelse
elif
is used to check several conditionselse
evalues a default block of code if all other conditions areFalse
the end of the entire
if
statement is where the indentation returns to the same level as the firstif
keyword
x = 5
if x > 10:
print("greater than 10")
elif x <= 10 and x > 5:
print("between 5 and 10")
elif x > 0 and x <= 5:
print("between 0 and 5")
else:
print("smaller than or equal to 0")
between 0 and 5
x = 100
if x > 10:
print("greater than 10")
elif x <= 10 and x > 5:
print("between 5 and 10")
elif x > 0 and x <= 5:
print("between 0 and 5")
else:
print("smaller than or equal to 0")
greater than 10
x = -1
if x > 10:
print("greater than 10")
elif x <= 10 and x > 5:
print("between 5 and 10")
elif x > 0 and x <= 5:
print("between 0 and 5")
else:
print("smaller than or equal to 0")
smaller than or equal to 0
Python allows “inline” if
statements, which can help make your code easier to read.
my_list = [0, 1, 2, 3, 4]
x = "more than 4 elements" if len(my_list) > 4 else "less than or equal to 4 elements"
x
'more than 4 elements'
Line 3 is shorthand for the following:
if len(my_list) > 4:
x = "more than 4 elements"
else:
x = "less than or equal to 4 elements"
x
'more than 4 elements'
A common pattern is to use the in
keyword to test if an element is in a list.
x = 4
if x in my_list:
print(f"{x} is in my_list")
else:
print(f"{x} is not in my_list")
x = 6
if x in my_list:
print(f"{x} is in my_list")
else:
print(f"{x} is not in my_list")
4 is in my_list
6 is not in my_list
Another useful pattern is to use in
to test if a key is in a dictionary. In addition, we can test if a variable is not None by using the keywords is not
.
my_dict = {"key1": "val1", "key2": False, "key3": 3}
k = "key3"
val = my_dict[k] if k in my_dict.keys() else None
if val is not None:
print(f"val is {val}")
else:
print(f"{k} is not a key in my_dict")
val is 3
k = "key4"
val = my_dict[k] if k in my_dict.keys() else None
if val is not None:
print(f"val is {val}")
else:
print(f"{k} is not a key in my_dict")
key4 is not a key in my_dict
Loops¶
A for loop allows some code to be executed a specific number of times.
The keyword
for
begins the loop, and the colon:
ends the first line of the loop.The block of code indented is executed for each value in the list (hence the name “for” loops)
We can iterate over any kind of “iterable”:
list
,tuple
,range
,set
,string
. An iterable is really just a sequence of values that can be looped over.
my_list = [0, 1, 2, 3]
for i in my_list:
print(i)
0
1
2
3
The builtin function range
can be used to iterate over a list of integers:
range(start, end, step)
is a list of the numbers between start and end with each subsequent number separted by step.range(n)
is short forrange(0,n,1)
for i in range(2, 20, 2):
print(i)
2
4
6
8
10
12
14
16
18
for i in range(5):
print(i)
0
1
2
3
4
Loops can be nested:
my_list1 = [0, 1, 2, 3]
my_list2 = ["A", "B", "C", "D"]
for i in my_list1:
for j in my_list2:
print(i, j)
0 A
0 B
0 C
0 D
1 A
1 B
1 C
1 D
2 A
2 B
2 C
2 D
3 A
3 B
3 C
3 D
The above nested loop outputs the product of the two lists, but often it will be important to match the elements of the two lists:
my_list1 = [0, 1, 2, 3]
my_list2 = ["A", "B", "C", "D"]
for idx in range(len(my_list1)):
print(my_list1[idx], my_list2[idx])
0 A
1 B
2 C
3 D
There is a much easier way to do this using the zip
builtin function:
for i in zip(my_list1, my_list2):
print(i[0], i[1])
0 A
1 B
2 C
3 D
The builtin function enumerate
adds a counter to the loop:
my_list2 = ["A", "B", "C", "D"]
for idx,item in enumerate(my_list2):
print(f"index {idx}", f"item {item}")
index 0 item A
index 1 item B
index 2 item C
index 3 item D
There is also a while
loop to excute a block of code several times.
i = 0
while i < 5:
print(i)
i += 1 # shorthand for i = i + 1
0
1
2
3
4
Comprehensions¶
Comprehensions are used to build lists/tuples/sets/dictionaries in one convenient, compact line of code. Below is a standard for
loop you might use to iterate over an iterable and create a list:
even_integers = list()
for i in range(10):
if i % 2 == 0:
even_integers.append(i)
print(even_integers)
[0, 2, 4, 6, 8]
Lines 1 - 4 can the nicely reduced to a single line of code:
event_integers = [i for i in range(10) if i % 2 == 0]
print(even_integers)
[0, 2, 4, 6, 8]
Comprehensions can also be used to create a dictionary:
ws = ["Philosophy", "Politics", "Economics"]
d = {w: len(w) for w in ws}
print(d)
{'Philosophy': 10, 'Politics': 8, 'Economics': 9}
Functions¶
A function is a reusable piece of code that can accept input parameters, also known as “arguments”. For example, the following function called square
takes one argument n
and returns the square n**2
:
def square(n):
return n ** 2
square(5)
25
A function can have local variables which are not accessible outside of the function.
def f_with_local_variable():
local_var = "defined inside the function"
print(local_var)
f_with_local_variable() # executes the function
local_var # produces and error since local_var is only accessible inside the function
defined inside the function
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-87-6bbdf2d7fb47> in <module>
4
5 f_with_local_variable() # executes the function
----> 6 local_var # produces and error since local_var is only accessible inside the function
NameError: name 'local_var' is not defined
Functions can return more than one value:
def f_return_2_values(i):
return i + i, i * i
f_return_2_values(5)
(10, 25)
You can unpack the returned values as follows:
val1, val2 = f_return_2_values(7)
print("val1 is ", val1)
print("val2 is ", val2)
val1 is 14
val2 is 49
It is often convenient to set a default value of a parameter (such parameters are called keyword parameters):
def add_n(i, n = 10):
return i + n
print(add_n(5))
print(add_n(5, n=100))
15
105
When designing a function, you should be careful not to modify any of the parameters:
def sum_arr(arr):
arr.append(0)
return sum(arr)
arr = [1, 2, 3, 4, 5]
print(sum_arr(arr))
print(arr) # note that 0 was added to arr!
15
[1, 2, 3, 4, 5, 0]
Imports¶
We will often need to use Python code created by others (often called a Python package). To do this we use the import
keyword. For example, Python does not have an implementation of a factorial as a builtin function. Rather than implementing this function ourselves, we can import the Python math package to use its factorial function.
import math # import the math package
math.factorial(5)
120
Sometimes we want to use our own naming convention for the imported Python package:
import math as m # rename the math package as m
m.factorial(5)
120
Rather than importing an entire package, it is more efficent to import the specific function that is needed:
from math import factorial
factorial(5)
120
You can also rename the imported function:
from math import factorial as fact
fact(5)
120
There is a lot more to say about Python packages and imports. See https://realpython.com/python-import/ for an overview.
Note
This only scratches the surface of Python. The best way to learn Python is to get your hands dirty and start playing around with code. Python is a very popular programming language, so you can find a lot of tutorials and courses online. When you need help search Google (you will probably find a lot of answers at https://stackoverflow.com/. Have fun!