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 + 2
3
>>> 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.py
Hello world!
%
>>> welcome_message = "Hello world!" # this is an assignment statement >>> print(welcome_message) # another statement
Hello world!
>>> 1 + 2 # expression statement with one expression combining the + operator with the values 1 and 2
3
"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 * 3
7
>>> (1 + 2) * 3 # () change operations' order
9
>>> 3 ** 2 # power, equivalent to pow(3, 2)
9
>>> 7.5 / 2. # quotient
3.75
>>> 7.5 // 2. # floored quotient
3.0
>>> 7.5 % 2. # remainder
1.5
>>> 2.5 * 1e2
250.0
>>> 2.5 == 3.75
False
>>> (2.5 <= 3.75) and (3.75 < 5)
True
>>> 2.5 <= 3.75 < 5 # this is also permitted
True
>>> float(3) # cast (convert) int to float
3.0
>>> 2 + 4.7 # 2 is converted to float before sum
6.7
>>> 1 + 3j + 2 + 0.4J # both j and J accepted
(3+3.4j)
>>> 1 + 4 j # beware of space in imaginary part
File "<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) == 4
True
>>> 4 == 4.0 # different numeric types, same value
True
>>> 4 == "4" # "4" is non-numeric (string)
False
>>> 3 * False + 5. * True + True
6.0
>>> (3 < 5) and (6 < 2) # both operands evaluated
False
>>> (3 < 5) or (6 < 2) # only (3 < 5) evaluated
True
>>> (3 > 5) and (2 < 6) # only (3 > 5) evaluated
False
>>> bool(-4.75) # cast to boolean
True
>>> 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 sense
Traceback (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 animals
Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'cat' is not defined
>>> "cat" in animals # check membership
True
>>> ("dog" in animals) and ("elephant" not in animals)
True
>>> domestic_animals = ["cat", "dog", "chicken"] >>> domestic_animals == animals # equality test
True
>>> domestic_animals is animals # identity test
False
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]
0
start
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 int
Traceback (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 arguments
Arthur 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 arguments
Arthur Conan Doyle was born in Edinburgh.
>>> print("You scored {:.2%} on the exam!".format(0.95)) # format as percentage w/2 significant digits
You 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 identity
140385175741424
>>> 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 object
140385175731376
>>> 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 -> 2
3
>>> add(b=3, a=4) # 3 and 4 are keyword args, bindings are based on name associations, not order: a -> 4, b -> 3
7
>>> 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 list
animals: ['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 altered
animals: ['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 directly
1
>>> 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 / 0
Traceback (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 list
0
>>> 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]
0
l[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 0
lion
>>> print(animals[-3]) # third member from the end of the list
cat
>>> 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 test
True
>>> 3 in numbers
True
>>> 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 exception
Traceback (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 changed
Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment
t[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 tests
True
>>> numbers.count(7)
2
>>> numbers.index(7) # index of first occurrence of 7 in the tuple
3
>>> numbers.index(7, 5) # index of first occurrence of 7 starting from index 5
7
>>> 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 unhashables
Traceback (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 testing
True
>>> 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} <= s1
True
>>> 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 &= s2 s1 |= s2 s1 -= s2 s1 ^= 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 error
Traceback (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 keys
Traceback (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 == d4
True
>>> 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 keys
1
>>> print(d["e"]) # using a key that doesn't exist raises an exception
Traceback (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 exception
None
>>> print(d.get("e", 0) # the default value can be customized
0
>>> 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