if, while, for statements,
...)python command in the Unix shell
(terminal)
>>>)
quit() to exit the interpreter% python
Python 3.8.5 (default, Aug 5 2020, 03:39:04)
[Clang 10.0.0 ] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.>>> welcome_message = "Hello world!"
>>> print(welcome_message)Hello world!>>> 1 + 23>>> quit() # exit() or [ctrl + d] ([ctrl + z] for Windows) also works%
.py source file) as an
argument
Content of hello_world.py file
# -*- coding: utf-8 -*- welcome_message = "Hello world!" print(welcome_message) 1 + 2
Execution
% python hello_world.pyHello world!%
>>> welcome_message = "Hello world!" # this is an assignment statement
>>> print(welcome_message) # another statementHello world!>>> 1 + 2 # expression statement with one expression combining the + operator with the values 1 and 23
"Hello world!" is an object of type str
(string)
1 and 2 are objects of type
int (integer)
print is an object of type
builtin_function_or_method
(more on functions later)
Syntax
variable_name = expression
Examples
>>> welcome_message = "Hello world!"
>>> print(welcome_message)Hello world!>>> a, b = 1, 2 # multiple assignments can be done in the same statement
>>> print(a)1>>> print(b)2>>> a += b # augmented assignment statement, equivalent to a = a + b
>>> print(a)3
A-Z, a-z),
digits (0-9), and
underscores ( _ )
a, B,
foo, bar_2_3, _name,
snake_case_name, mixedCaseName,
CamelCaseName, UPPERCASENAME, ...
2items, return,
name with spaces, ab>cd@3,
X Æ A-12
(sorry, Elon Musk 😢), ...
foo and Foo are two
different names!
name and age are better names than
n and a!
snake_case names for variables (and
functions).
#) and ends at the end of
a physical line
int) :
1, 3, -5, ...
float): 1.,
2.45, 3.5e-6, ...
complex):
1 + 2j, 4.5j, ...
.) or exponent sign
(e) → floating point
number
j
(or J)
→ complex number
+, -, *,
/, %, ...)
==, !=, <,
>, <=, >=)
>>> 1 + 2 * 37>>> (1 + 2) * 3 # () change operations' order9>>> 3 ** 2 # power, equivalent to pow(3, 2)9>>> 7.5 / 2. # quotient3.75>>> 7.5 // 2. # floored quotient3.0>>> 7.5 % 2. # remainder1.5>>> 2.5 * 1e2250.0>>> 2.5 == 3.75False>>> (2.5 <= 3.75) and (3.75 < 5)True>>> 2.5 <= 3.75 < 5 # this is also permittedTrue>>> float(3) # cast (convert) int to float3.0>>> 2 + 4.7 # 2 is converted to float before sum6.7>>> 1 + 3j + 2 + 0.4J # both j and J accepted(3+3.4j)>>> 1 + 4 j # beware of space in imaginary partFile "<stdin>", line 1
1 + 4 j
^
SyntaxError: invalid syntax
False and
True are used by Python to represent
truth values
False and None constants0, 0.0,
0j, ...
"", {},
(), [], ...
(more on these later)
0 and 1) in
numeric contexts (e.g., with arithmetic operations)
| Operation | Meaning |
|---|---|
< |
Strictly less than |
<= |
Less than or equal to |
> |
Strictly greater than |
>= |
Greater than or equal to |
== |
Equal to |
!= |
Not equal to |
is |
Object identity |
is not |
Negated object identity |
in* |
Member of |
not in* |
Not member of |
* Supported by iterable types (more details later)
<, <=, >, and
>= are only defined where it makes sense
| Operation | Result |
|---|---|
x or y |
if x is false, then y, else
x
|
x and y |
if x is false, then x, else
y
|
not x |
if x is false, then True, else
False
|
and and or are short-circuit operators:
the second argument is not always evaluated
and and or return one of their operands,
not boolean results
0 or False for false and
1 or True for true
>>> (1 + 3) == 4True>>> 4 == 4.0 # different numeric types, same valueTrue>>> 4 == "4" # "4" is non-numeric (string)False>>> 3 * False + 5. * True + True6.0>>> (3 < 5) and (6 < 2) # both operands evaluatedFalse>>> (3 < 5) or (6 < 2) # only (3 < 5) evaluatedTrue>>> (3 > 5) and (2 < 6) # only (3 > 5) evaluatedFalse>>> bool(-4.75) # cast to booleanTrue>>> 7.5 or True # and and or return operands (!!!)7.5>>> True or 7.5 # and and or return operands (!!!)True>>> 1 < (1 + 4j) # < does not make senseTraceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances
of 'int' and 'complex'
>>> # don't worry if you don't fully understand the next
>>> # examples
>>> animals = ["cat", "dog", "chicken"] # a list of animals
>>> cat in animalsTraceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'cat' is not defined>>> "cat" in animals # check membershipTrue>>> ("dog" in animals) and ("elephant" not in animals)True>>> domestic_animals = ["cat", "dog", "chicken"]
>>> domestic_animals == animals # equality testTrue>>> domestic_animals is animals # identity testFalse
str objects'This is a string'"This is another string""""Yet another string""" or
'''Same but with single quotes'''
') in single quote
strings, can be escaped using backslash (\)
\' (single quote),
\" (double quote), \n (line feed),
\t (horizontal tab), \v (vertical tab), ...
+ operator (can be
incompatible with other types)
string[start:end:step]
0start is included,
end is excluded
start omitted → 0
end omitted →
last_index + 1
step omitted → 1
lower(), upper(), ... → change
letters casing
lstrip(), rstrip(), ... → handle
trailing white space
islower(), isalpha(),
isdecimal(), ... → verify properties
>>> "Hello" + "world" + "!" # string concatenation'Helloworld!'>>> "John's age is " + 30 # try to concatenate with intTraceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str>>> "John's age is " + str(30)"John's age is 30">>> 3 * "Hello! "'Hello! Hello! Hello! '>>> alphabet = "abcdefghijklmnopqrstuvwxyz"
>>> alphabet[0]'a'>>> alphabet[-1] # reverse order indexing'z'>>> alphabet[:4] # slicing (same as alphabet[0:4])'abcd'>>> alphabet[4:7] # 5th to 6th character 'efg'>>> alphabet[20:] # slice from 21st character to end of string'uvwxyz'>>> alphabet[::2] # one every two characters'acegikmoqsuwy'>>> alphabet[-1:-6:-1] # last five characters in reverse order'zyxwv'>>> book = "The Hound of the Baskervilles"
>>> book.upper()'THE HOUND OF THE BASKERVILLES'>>> book.split() # split into a list of words['The', 'Hound', 'of', 'the', 'Baskervilles']>>> " Too much trailing whitespace ".strip()'Too much trailing whitespace'>>> "Hi!".isalpha()False>>> "1234".isnumeric()True
format() method
{}
{name}, {age},
...) of keyword arguments or numeric indexes (e.g.,
{0}, {1}, ...) of positional arguments
:%, :.2f, ...) that customize their
presentation
Syntax
format_string.format(value_1, value_2, ...)
>>> author = "Arthur Conan Doyle"
>>> book = "The Hound of the Baskervilles"
>>> birthplace = "Edinburgh"
>>> print("{} was originally published in {}.".format(book, 1902))The Hound of the Baskervilles was originally published in 1902.>>> print("{1} is the author of {0}.".format(book, author)) # using indexes of positional argumentsArthur Conan Doyle is the author of The Hound of the Baskervilles.>>> print("{name} was born in {birthplace}.".format(name=author, birthplace=birthplace)) # using names of keyword argumentsArthur Conan Doyle was born in Edinburgh.>>> print("You scored {:.2%} on the exam!".format(0.95)) # format as percentage w/2 significant digitsYou scored 95.00% on the exam!>>> print("The world's population in {year} was {population:,.0f}.".format(year=2018, population=7.59e9))The world's population in 2018 was 7,590,000,000.
int, float, bool, and
str objects are all immutable
list): ordered sequence of objects["cat", "dog", "chicken"]set): unordered collections of unique objects
{"cat", "dog", "chicken"}dict): key → value mappings{"name" : "Cloud", "age": 21, "job": "mercenary"}
>>> text = "Meat"
>>> id(text) # check object's identity140385175741424>>> text[2] = "e" # trying to modify the string will raise an exception (result in an error)Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment>>> text = text + " is delicious!"
>>> print(text)Meat is delicious!>>> id(text) # text is now bound to a new object140385175731376>>> animals = ["cat", "dog", "chicken"]
>>> id(animals)140385175649664>>> animals[2] = "duck" # try to replace the third member of the list
>>> animals['cat', 'dog', 'duck']>>> id(animals) # re-check the object's identity (it remains the same)140385175649664
if statement)
while statement)
for statement)
if, while, and for statements are
examples of
compound statements, i.e., statements that contain and affect the execution of (groups of)
other statements.
if StatementsThe statement is executed as follows
if clause's
header is evaluated
Syntax (simple form)
if expression:
statement_1
statement_2
...
statement_n
rest_of_program
Flow diagram (simple form)
if StatementsThe statement is executed as follows
if clause's header is true
elif (optional) clauses
else (optional) clause is executed
Syntax (general form)
if expression_1:
statement_1
...
elif expression_2:
...
...
elif expression_n:
...
else:
...
rest_of_program
if StatementsFlow diagram (general form)
Syntax (general form)
if expression_1:
statement_1
...
elif expression_2:
...
...
elif expression_n:
...
else:
...
rest_of_program
if Statements ExampleCode
number = int(input("Please enter an integer: ")) # ask user to provide input if (number % 2): print("{} is an odd number".format(number)) elif not ((number % 3) or (number % 4)): print("{} is even and can be divided by both 3 and 4".format(number)) elif number > 10: print("{} is even and greater than 10".format(number)) print("Finished") # rest of the program
Outputs of different executions
Please enter an integer: 1
1 is an odd number
Finished
Please enter an integer: 8
Finished
Please enter an integer: 12
12 is even and can be divided by both 3 and 4
Finished
Please enter an integer: 16
16 is even and greater than 10
Finished
while StatementsThe statement is executed as follows
while clause's header is
evaluated
while statement loops on itself (i.e., goes back
to the expression evaluation step)
break statement or never alters how the expression
evaluates, the while statement will loop indefinitely!
Syntax
while expression:
statement_1
statement_2
...
statement_n
rest_of_program
Flow diagram
while Statements Examples>>> i = 0
>>> while (i < 5):
... print(i)
... i += 1 # if i never changes, the loop will print 0 indefinitely
... 0
1
2
3
4>>> i, j = 0, 1
>>> while (i < 10):
... j += 1
... print("i = {}. j = {}.".format(i, j))
... if (j == 4): # if j reaches 4, break out of the loop
... break
... i = 0. j = 2.
i = 0. j = 3.
i = 0. j = 4.
for Statements
The for statement is executed as follows
element is bound to that object
for (and
while) statements can contain an
else clause.
Syntax
for element in expression:
statement_1
statement_2
...
statement_n
rest_of_program
Flow diagram
str), lists*
(list), tuples* (tuple), ranges
(range), ...
set), frozen sets*
(frozenset), dictionaries* (dict), ...
* Will be discussed in detail in the Data Structures section of the course
for Statements Examples>>> for char in "Hello": # you can iterate over strings (sequences of characters)
... print(char)
... H
e
l
l
o>>> for i in range(10): # range objects are immutable sequences of integers (0–9 here)
... print(i)
... if i == 5:
... break # you can also break out of for loops
... 0
1
2
3
4
5>>> animals = ["cat", "dog", "chicken"] # a list of animals
>>> for animal in animals:
... print(animal)
... cat
dog
chicken>>> for i, animal in enumerate(animals): # use the enumerate() function if you need the index while looping
... print("animals[{}] contains {}.".format(i, animal))
... animals[0] contains cat.
animals[1] contains dog.
animals[2] contains chicken.
>>> animals = ["cat", "dog", "chicken"] # a list of animals
>>> # this is bad
>>> i = 0
>>> while (i < len(animals)): # len() returns the length (number of elements) of a sequence or a collection
... print(animals[i])
... i += 1
... cat
dog
chicken>>> for i in range(len(animals)): # this is equally bad
... print(animals[i])
... cat
dog
chicken>>> for animal in animals: # the most idiomatic (pythonic) way
... print(animal)
... cat
dog
chicken
break and continue Statementsbreak or
continue statements
for and while loopsbreak → terminates the nearest enclosing loopcontinue → continues with the next cycle of the
nearest enclosing loop (terminates the current cycle only)
>>> for i in range(1, 10):
... if not (i % 3):
... continue # only iterations involving multiples of 3 are skipped
... print(i)
... 1
2
4
5
7
8>>> for i in range(1, 10):
... if not (i % 3):
... break # as soon as the 1st multiple of 3 is encountred, execution of all subsequent loops is skipped
... print(i)
... 1
2
print(),
input(), len(), enumerate(), ...
format(),
upper(), isnumeric(),
isalpha() (all defined for str objects), ...
Syntax
def function_name(param_1, param_2, ...):
statement_1
statement_2
...
def statements(), potentially enclosing a
sequence of comma-separated parameters (inputs used by the
function)
function object (the executable code)
Syntax
function_name(arg_1, arg_2, ...)
>>> def say_hi(): # function definition with no parameters
... print("Hi!")
...
>>> say_hi() Hi!>>> def add(a, b): # function definition with two parameters a and b
... print(a + b)
...
>>> add(5, 10) # function call: a is bound to 5, b to 10, and the body is executed 15
return StatementsSyntax (inside function definition only)
return expression_list
Example
>>> def add(a, b):
... return a + b
...
>>> a = add(7, 10) # a is not the parameter
>>> b = add(20, 5) # same for b
>>> c = add(a, b)
>>> print(c)42
return statements
return statement is encountredreturn statement,
then its value is None
global and nonlocal statements change how a
name is resolved
global → direct reference to global namespacenonlocal → direct reference to nearest enclosing
namespace
Code (scroll down to see the rest)
l = [1, 2, 3] def outer_func(): l = [4, 5, 6] def inner_func_a(): l = [7, 8, 9] print("Inside inner_func_a:", l) def inner_func_b(): global l # will be looked up in top-most scope -> global print("Inside inner_func_b:", l) def inner_func_c(): nonlocal l # looked up in nearest enclosing scope -> outer_func() print("Inside inner_func_c:", l) def inner_func_d(): nonlocal l l = [10, 11, 12] # modify binding print("Inside inner_func_d:", l) def inner_func_e(): nonlocal l l.append(42) # modify list print("Inside inner_func_e:", l) print("Before inner_func_* calls:", l) inner_func_a() print("After inner_func_a call:", l) inner_func_b() print("After inner_func_b call:", l) inner_func_c() print("After inner_func_c call:", l) inner_func_d() print("After inner_func_d call:", l) inner_func_e() print("After inner_func_e call:", l) print("Before outer_func call:", l) outer_func() print("After outer_func call:", l)
Output
Before outer_func call: [1, 2, 3]
Before inner_func_* calls: [4, 5, 6]
Inside inner_func_a: [7, 8, 9]
After inner_func_a call: [4, 5, 6]
Inside inner_func_b: [1, 2, 3]
After inner_func_b call: [4, 5, 6]
Inside inner_func_c: [4, 5, 6]
After inner_func_c call: [4, 5, 6]
Inside inner_func_d: [10, 11, 12]
After inner_func_d call: [10, 11, 12]
Inside inner_func_e: [10, 11, 12, 42]
After inner_func_e call: [10, 11, 12, 42]
After outer_func call: [1, 2, 3]
function_name(arg_1, arg_2, ...)
function_name(param_1=arg_1,param_2=arg_2, ...)
>>> def add(a, b):
... return a + b
...
>>> add(1, 2) # 1 and 2 are positional args, params are bound in order: a -> 1, b -> 23>>> add(b=3, a=4) # 3 and 4 are keyword args, bindings are based on name associations, not order: a -> 4, b -> 37>>> add(4, b=10) # positional and keyword args can be mixed: a -> 4 (based on order), b -> 10 (based on name)14>>> add(a=1, 3) # positional args must appear first (once a kwarg appears, all those that follow must be kwargs) File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument>>> add(*[3, 5]) # (advanced) lists can be "unpacked" into positional args (equivalent to add(3, 5))8>>> add(**{ "b": 7, "a": 4}) # (advanced) dicts can be unpacked into kwargs (equivalent to add(a=4, b=7))11
>>> def add_animal(animal, animal_list):
... animal_list.append(animal) # add new animal to list
... return animal_list
...
>>> def reassign_animals(animal_list):
... animal_list = ["dove", "sparrow", "eagle"] # rebind the name to a new list
... return animal_list
...
>>> animals = ["cat", "dog", "chicken"]
>>>
>>> reassigned_animals = reassign_animals(animals)
>>>
>>> print("animals:", animals) # animals is still bound to the same listanimals: ['cat', 'dog', 'chicken']>>> print("reassigned_animals:", reassigned_animals)reassigned_animals: ['dove', 'sparrow', 'eagle']>>> new_animals = add_animal("elephant", animals)
>>>
>>> print("animals:", animals) # animals did get alteredanimals: ['cat', 'dog', 'chicken', 'elephant']>>> print("new_animals:", new_animals)new_animals: ['cat', 'dog', 'chicken', 'elephant']
def function_name(param_1, ..., param_i=expression_i, ..., param_n=expression_n):
function_body
>>> def add(a=1, b): # params with non-default values must precede those that have defaults
... return a + b
... File "<stdin>", line 1
SyntaxError: non-default argument follows default argument>>> def add(a, b=1): # b has a default value of 1
... return a + b
...
>>> add(5) # equivalent to add(5, 1)6
The following code...
def append_to(element, to=[]): to.append(element) return to my_list = append_to(12) print(my_list) my_other_list = append_to(42) print(my_other_list)
... outputs
[12]
[12, 42]
Example*
>>> def factorial(number):
... if number > 0: # recursive case
... return number * factorial(number - 1)
... else: # trivial case (number == 0)
... return 1
...
>>> factorial(0) # solved directly1>>> factorial(3) # factorial(3) -> calls factorial(2) -> calls factorial(1) -> calls factorial(0)6
* Something is fishy in this example. Can you point it out?
Syntax
def function_name(param_1: type_1, param_2: type_2, ...) -> return_type:
function_body
Example
>>> def add(a: int, b: int = 1) -> int:
... return a + b
...
>>> add(1, 2)3>>> add("Hello", "world") # this does not generate an error even though strings are used!'Helloworld'
Syntax
def function_name(...):
"""Function documentation (docstring)"""
rest_of_function_body
>>> def add(a: int, b: int = 1) -> int:
... """Add two integers.
...
... Args:
... a (int): The first integer.
... b (int, optional): The second integer. Defaults to 1.
...
... Returns:
... int: The sum of the two integers.
... """
... return a + b
...
: is
missing, a statement is wrongly indented, ...)
>>> for i in [1 , 2, 3] print(i)File "<stdin>", line 1
for i in [1 , 2, 3] print(i)
^
SyntaxError: invalid syntax>>> x = 3 / 0Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
raise statements can be used to raise exceptions so that
they can be handled by the surrounding code
(cf. next slide)
>>> def add(a: int, b: int = 1) -> int:
... """Add two integers.
...
... Args:
... a (int): The first integer.
... b (int, optional): The second integer. Defaults to 1.
...
... Returns:
... int: The sum of the two integers.
... """
... if not (isinstance(a, int) and isinstance(b, int)):
... raise TypeError("Arguments must be of type int") # stops the function's execution
... return a + b # only executed if no exceptions are raised
...
Syntax
try:
try_body
except (ErrorType1, ErrorType2, ...):
except_body
try (compound)
statements
try clause is executedexcept clause is skipped
except keyword
except clause is executedtry statement
>>> try:
... add("toto", 1)
... except TypeError:
... print("Oups! Something went wrong!!!")Oups! Something went wrong!!!
list): mutable sequences of objectstuple): immutable sequences of objectsset): collections of unique objectsdict): mappings between key-value pairs
list) are sequences of objects
l[i])
l[start:end:step])
>>> animals = ["cat", "dog", "chicken"]
>>> mixed_list = [1, "pen", True, [1., 2.5, 3+4j]]
>>> print(animals)['cat', 'dog', 'chicken']>>> print(mixed_list)[1, 'pen', True, [1.0, 2.5, (3+4j)]]
[]
[item_1, item_2, ...]
list() (for an empty list) or
list(iterable)
list_1 + list_2
n * l (concat
the list l with itself
n times)
>>> empty_list = []
>>> print(empty_list)[]>>> print(len(empty_list)) # print the length (number of members) of the list0>>> alphabet = "abcdefghijklmnopqrstuvwxyz"
>>> alphabet_list = list(alphabet) # using the type constructor list() applied to an iterable
>>> print(alphabet_list)['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']>>> wild_animals = ["lion", "giraffe", "elephant"]
>>> domestic_animals = ["cat", "dog", "chicken"]
>>> animals = wild_animals + domestic_animals # list concatenation
>>> print(animals)['lion', 'giraffe', 'elephant', 'cat', 'dog', 'chicken']>>> 3 * [1, 2, 3] # concatenate the list with itself three time[1, 2, 3, 1, 2, 3, 1, 2, 3]
for loopsl[i]
0l[start:end:step]
start is inclusive
end is exclusive
start → 0;
end → len(l);
step →
1
>>> animals = ["lion", "giraffe", "elephant", "cat", "dog", "chicken"]
>>> print(animals[0]) # remember: positions start at 0lion>>> print(animals[-3]) # third member from the end of the listcat>>> print(animals[:3]) # slice of the three first members of the list['lion', 'giraffe', 'elephant']>>> domestic_animals = animals[3:] # create a new list based on members from 4th pos. -> end of list
>>> print(domestic_animals)['cat', 'dog', 'chicken']>>> print(animals[1::2]) # select one every two animals, starting from 2nd item['giraffe', 'cat', 'chicken']>>> domestic_animals[1] = "sheep" # you can use indexes to modify individual list members
>>> print(domestic_animals)['cat', 'sheep', 'chicken']>>> print(animals) # the original list from which domestic_animals was created was not modified['lion', 'giraffe', 'elephant', 'cat', 'dog', 'chicken']>>> animals[:4:2] = ["tiger", "zebra"] # slicing can also be used to modify multiple items simultaneously
>>> print(animals)['tiger', 'giraffe', 'zebra', 'cat', 'dog', 'chicken']
len(l): length (number of members) of the list
l
x in l: check if object x is a member of the list
l
True if a member of
l equals x, False otherwise
x not in l (check that
x is not a member of l)
l.append(x): insert object
x at the end of the list l
l.insert(i, x): insert object
x at position i of the list
l
l.count(x): number of occurrences of
object x in the list
l
l.remove(x): remove the first occurrence
of x in the list l
l.pop(i): pop (remove) the member at
position i and return it
l.clear(): empty the list l
l.sort(): sort the list
l (in-place)
l.reverse(): invert the list
l (in-place)
max(l), min(l): largest /
smallest item in the list
* The supported sequence operations and their priorities can be found here and here.
>>> numbers = [2, 4, 27, 1, -5, 11, 3]
>>> len(numbers)7>>> 25 not in numbers # membership testTrue>>> 3 in numbersTrue>>> numbers.append(27) # append 27 at the end of the list
>>> print(numbers)[2, 4, 27, 1, -5, 11, 3, 27]>>> numbers.insert(3, 42)
>>> print(numbers)[2, 4, 27, 42, 1, -5, 11, 3, 27]>>> numbers.count(27)2>>> numbers.remove(27) # remove the first occurrence of 27 from the list
>>> print(numbers)[2, 4, 42, 1, -5, 11, 3, 27]>>> numbers.remove(33) # trying to remove an item that doesn't exist raises an exceptionTraceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list>>> numbers.sort(reverse=True) # sort the list in reverse order (the list is directly modified)
>>> print(numbers)[42, 27, 11, 4, 3, 2, 1, -5]>>> n = numbers.pop(3) # pop the 4th item from the list and bind the name n to it
>>> print(numbers)[42, 27, 11, 3, 2, 1, -5]>>> print(n)4
element is bound to the object
expression is evaluated
Syntax
[expression for element in iterable]
Example
>>> numbers_squared = [n**2 for n in range(1, 11)]
>>> print(numbers_squared)[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]>>> # equivalent to
>>> numbers_squared = []
>>> for n in range(1, 11):
... numbers_squared.append(n**2)
...
>>> print(numbers_squared)[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
if clauses to filter
expressions based on some condition
Syntax
[expression for element in iterable if condition]
Example
>>> odd_numbers = [n for n in range(10) if (n % 2)]
>>> print(odd_numbers)[1, 3, 5, 7, 9]>>> # equivalent to
>>> odd_numbers = []
>>> for n in range(10):
... if (n % 2):
... odd_numbers.append(n)
...
>>> print(odd_numbers)[1, 3, 5, 7, 9]
for statements
Syntax
[expression for x in iterable_1 for y in iterable_2]
Example
>>> numbers = [2 * x + y for x in range(3) for y in range(0, 50, 10)]
>>> print(numbers)[0, 10, 20, 30, 40, 2, 12, 22, 32, 42, 4, 14, 24, 34, 44]]>>> # equivalent to
>>> numbers = []
>>> for x in range(3):
... for y in range(0, 50, 10):
... numbers.append(2 * x + y)
...
>>> print(numbers)[0, 10, 20, 30, 40, 2, 12, 22, 32, 42, 4, 14, 24, 34, 44]
tuple) are sequences used typically to store
collections of heterogeneous data
>>> animals = ("cat", "dog", "chicken")
>>> mixed_tuple = (1, "pen", True, [1., 2.5, 3+4j])
>>> print(animals)['cat', 'dog', 'chicken']>>> print(mixed_tuple)(1, 'pen', True, [1.0, 2.5, (3+4j)])
()
(a,) or
a,
(a, b, c) or
a, b, c
tuple() (for an empty tuple)
or tuple(iterable)
tuple_1 + tuple_2
n * t
>>> t = () # an empty tuple, equivalent to using the type constructor tuple()
>>> print(t)()>>> t = 1, # singleton tuple
>>> type(t)<class 'tuple'>>>> print(t)(1,)>>> t = (1, 2, 3) # same as t = 1, 2, 3
>>> print(t)(1, 2, 3)>>> t = (1, 2, 3) + (4, 5, 6) # tuple concatenation
>>> print(t)(1, 2, 3, 4, 5, 6)
>>> t = 3 * (1, 2, 3) # tuple replication (concatenate tuple with itself multiple times)
>>> print(t)(1, 2, 3, 1, 2, 3, 1, 2, 3)>>> t = tuple(3*[[]]) # a tuple from a list of "three" empty lists
>>> print(t)([], [], [])>>> t[0].append("cat") # a little brain teaser: what is happening here???
>>> print(t)(['cat'], ['cat'], ['cat'])
>>> t = ("John", 23, ["Pasta", "Pizza", "Tiramisu"]) # name, age, and list of favorite dishes
>>> t[0] = "Jane" # The name (immutable str) can't be changedTraceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignmentt[2] = ["Fondue", "Raclette", "Tartiflette"] # the binding to the list can't be changed...Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment>>> t[2][0] = "Raclette" # ... but the list itself (mutable) can!
>>> t[2].append("Fondue")
>>> print(t)('John', 23, ['Raclette', 'Pizza', 'Tiramisu', 'Fondue'])
| Operation | Description |
|---|---|
len(t) |
Length (number of items) of the tuple t
|
x in t
|
True if a member of t equals
x, False otherwise
|
x not in t
|
False if a member of t equals
x, True otherwise
|
t.count(x)
|
Number of occurrences of x in the tuple
t
|
t.index(x)
|
Index of the first occurrence of x in the
tuple t
|
max(t) |
Largest item in the tuple t
|
min(t) |
Smallest item in the tuple t
|
>>> numbers = (1, 5, 2, 7, 8, 11, -3, 7, 42)
>>> print(len(numbers))9>>> print(numbers[3::2]) # tuples are subscriptable and support slicing(7, 11, 7)>>> (5 in numbers) and (12 not in numbers) # membership testsTrue>>> numbers.count(7)2>>> numbers.index(7) # index of first occurrence of 7 in the tuple3>>> numbers.index(7, 5) # index of first occurrence of 7 starting from index 57>>> print("Smallest number: {}. Largest number: {}.".format(min(numbers), max(numbers)))Smallest number: -3. Largest number: 42.>>> t = (i for i in range(10) if (i % 2)) # There are no tuple comprehensions!!!
>>> type(t)<class 'generator'>
enumerate() function builds a new iterable from another
iterable (passed as an argument)
>>> animals = ["cat", "dog", "chicken"]
>>> for t in enumerate(animals):
... print(t)
... (0, 'cat')
(1, 'dog')
(2, 'chicken')>>> for i, animal in enumerate(animals):
... print("The animal at position {} is {}".format(i, animal))
... The animal at position 0 is cat
The animal at position 1 is dog
The animal at position 2 is chicken
set) are unordered collections of unique
hashable
objects
frozenset built-in
type)
{item_1, item_2, ...}
set() (for an empty set) or
set(iterable)
{} does not
produce an empty set!
>>> type({}) # this is an empty dict (presented next), not an empty set (use set() instead)<class 'dict'>>>> s = {"Hello", 1, 3.14, 5+4j, (1, 2)} # type mixing is allowed...
>>> print(s){'Hello', 1, (1, 2), 3.14, (5+4j)}>>> s = { "Hello", 1, 3.14, 5+4j, (1, 2), [1, 4, 5] } # ... as long as you don't use unhashablesTraceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'>>> numbers = {1, 5, 2, 7, -2, 7, 4, 42, -8, 36, 42} # sets can't contain duplicates
>>> print(numbers){1, 2, 4, 5, 36, 7, 42, -8, -2}>>> s = {1, 2, 3} + {4, 5, 6} # sets do not support concatenations (or replication)Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'set' and 'set'>>> s = set(range(10)) # set() can be used to construct sets from iterables
>>> print(s){0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
{} instead of [])
expression must evaluate
to a hashable
Syntax
{expression for element in iterable}
Examples
>>> numbers_squared = {n**2 for n in range(1, 11)}
>>> print(numbers_squared){64, 1, 4, 36, 100, 9, 16, 49, 81, 25}>>> s = { (i, j) for i in range(4) for j in range(4) if i < j}
>>> print(s){(0, 1), (1, 2), (1, 3), (2, 3), (0, 3), (0, 2)}
| Operation | Description |
|---|---|
x in s
|
Returns True if x is an element
of s
|
x not in s
|
Returns True if x is not an
element of s
|
s1 == s2
|
Returns True if s1 and
s2 contain the same elements
|
s1.isdisjoint(s2)
|
Returns True if s1 and
s2 have no elements in common
|
s1.issubset(s2)s1 <= s2
|
Tests if s1 is a subset of
s2 (use
s1.issuperset(s2) or
s1 >= s2 for the other way around)
|
s1 < s2
|
Tests if s1 is a proper subset of
s2
(use s1 > s2 for the other way
around)
|
s1.intersection(s2)s1 & s2
|
Returns a new sets containing elements common to both
s1 and s2
|
s1.union(s2)s1 | s2
|
Returns a new sets containing elements of both
s1 and s2
|
s1.difference(s2)s1 - s2
|
Returns a new sets containing elements that are in
s1 but not in s2
|
s1.symmetric_difference(s2)s1 ^ s2
|
Returns a new sets containing elements that are in either
s1 or s2 but not both
|
>>> s1 = set(range(0, 30, 3))
>>> print(s1){0, 3, 6, 9, 12, 15, 18, 21, 24, 27}>>> s2 = set(range(0, 30, 4))
>>> print(s2){0, 4, 8, 12, 16, 20, 24, 28}>>> (9 in s1) and (12 in s2) # membership testingTrue>>> s1 & s2 # equivalent to s1.intersection(s2){0, 24, 12}>>> s1 | s2 # equivalent to s1.union(s2){0, 3, 4, 6, 8, 9, 12, 15, 16, 18, 20, 21, 24, 27, 28}>>> s1 - s2 # equivalent to s1.difference(s2){3, 6, 9, 15, 18, 21, 27}>>> s2 - s1{4, 8, 16, 20, 28}>>> s1 ^ s2 # equivalent to s1.symmetric_difference(s2){3, 4, 6, 8, 9, 15, 16, 18, 20, 21, 27, 28}>>> s1 <= s2 # equivalent to s1.issubset(s2)False>>> {3, 6, 9} <= s1True>>> s1 < s1 # s1 is not a proper subset of itself (since s1 == s1)False
s[i] = expression)
| Operation | Description |
|---|---|
s.add(x)
|
Adds x to the set
s (x must be hashable)
|
s.remove(x)
|
Removes x from s (raises
an exception if x not in s)
|
s.discard(x)
|
Removes x from s (does
not raises an exception if x not in s)
|
s.clear()
|
Empties the set s from all its elements
|
s.pop()
|
Removes an arbitrary element from the set
s and returns it
|
s1 &= s2s1 |= s2s1 -= s2s1 ^= s2
|
Update the set s1 by adding the result of the
corresponding set operation (intersection, union, difference, and
symmetric difference respectively) to s1 and
s2
|
>>> s = {5, 2, 42, -7, 3, -16}
>>> s.add(9)
>>> print(s){2, 3, 5, 9, 42, -16, -7}>>> s.remove(3)
>>> print(s){2, 5, 9, 42, -16, -7}>>> s.remove(101) # attempting to remove an alement that doesn't exist raises an errorTraceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 101>>> n = s.pop()
>>> print(s, ",", n){5, 9, 42, -16, -7} , 2>>> s -= {5, 4, -7}
>>> print(s){9, 42, -16}>>> s |= {3, 12} | {45, 9} ^ {3, 9}
>>> print(s){3, 9, 42, 12, 45, -16}>>> s.clear()
>>> print(s)set()
dict) are objects that map hashable values
(keys) to arbitrary objects (values)
>>> person = {"name": "John", "age": 24, "profession": "Data Scientist"}
>>> print(person){'name': 'John', 'age': 24, 'profession': 'Data Scientist'}>>> print(person["name"])John
dict) are objects that map hashable values
(keys) to arbitrary objects (values)
{}
key:value pairs inside:
{key_1: value_1, key_2:
value_2, ...}
dict() (for an empty
dictionary), dict(**kwargs),
dict(mapping, **kwargs), or
dict(iterable, **kwargs)
>>> d = {} # an empty dict, equivalent to d = dict()
>>> print(d, ", ", len(d)){} , 0>>> d = { 1: "Hello", (3, 5): 3+4j, "list": [1, 5]} # type mixing is accepted (for keys and values)...
>>> print(d)>>> d = { 1: "Hello", [3, 4, 2] : (1, 2)} # ... as long as you use hashable keysTraceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'>>> # The following are all equivalent constructions
>>> d1 = {"name": "John", "age": 24, "profession": "Data Scientist"}
>>> d2 = dict(name="John", age=24, profession="Data Scientist")
>>> d3 = dict([("name", "John"), ("age", 24), ("profession", "Data Scientist")])
>>> d4 = dict(zip(["name", "age", "profession"], ["John", 24, "Data Scientist"]))
>>> d1 == d2 == d3 == d4True>>> print(d1){'name': 'John', 'age': 24, 'profession': 'Data Scientist'}
zip() returns an iterable
object containing tuples obtained from iterating over multiple iterators
simultaneously (documentation).
{} like the
latter)
key_expression must produce a
hashable
Syntax
{key_expression: value_expression for element in iterable}
Examples
>>> print({i : i**2 for i in range(11)}){0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81, 10: 100}>>> print({i: animal for i, animal in enumerate(["cat", "dog", "chicken"])}{0: 'cat', 1: 'dog', 2: 'chicken'}>>> print({ animal: len(animal) for animal in ["cat", "dog", "chicken"] if len(animal) < 5 }){'cat': 3, 'dog': 3}
d[key] (not numeric indice)
key exists in the dictionary → returns
the associated value
KeyError exceptiond.get(key, default_value)
can also be used to access the dictionary's values
key exists in the dictionary → returns
the associated value
default_value is returned if it is specified
None is returned if
default_value is omitted
>>> d = {"a": 1, "b": 2, "c": 3}
>>> print(d["a"]) # indexation is done by keys1>>> print(d["e"]) # using a key that doesn't exist raises an exceptionTraceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'e'>>> print(d.get("e")) # using an inexistant key with get() doesn't raise an exceptionNone>>> print(d.get("e", 0) # the default value can be customized0>>> for i in d: # iterating directly on the dict operates on its keys
... print(i)
... a
b
c
d.keys() → Collection of keys in the
dictionary
d
d.values() → Collection of values in the
dictionary d
d.items() → Collection of (key, value) in
the dictionary d
in and
not in operators)
>>> d = {"a": 3, "b": 7, "c": 42, "d": 13}
>>> for key in d.keys():
... print(key)
... a
b
c
d>>> for value in d.values():
... print(value)
... 3
7
42
13>>> for key, value in d.items():
... print(key, " -> ", value)
... a -> 3
b -> 7
c -> 42
d -> 13
| Operation | Description |
|---|---|
d[key] = value
|
Insert the (key, value) pair in
d (updates
d[key] if it already exists)
|
del d[key]
|
Removes key from
d (raises a KeyError exception if
the key is not in the dict)
|
len(d) |
Length (number of items) of the dictionary d
|
x in d
|
True if a key of d equals
x, False otherwise
|
x not in d
|
False if a key of d equals
x, True otherwise
|
d.pop(key, default)
|
If key in d, removes the key and returns the associated value, else returns
default
|
d.popitem()
|
Removes and returns a
(key, value) pair from
d in LIFO (last in first out) order
|
d.clear()
|
Empty d from all its items
|
func(*args)
func(**kwargs)
>>> def add(a, b):
... return a + b
...
>>> l = [1, 2]
>>> d = {"a": 3, "b": 4}>>> add(*l) # equivalent to add(l[0], l[1])3>>> add(**d) # equivalent to add(a=d["a"], b=d["b"])7