"### Bonus: the Easier to Ask for Forgiveness than Permission (EAFP) principle\n",
"\n",
"There are several ways to perform the previous task:\n",
"\n",
"- In the solution presented above, we `try` first the conversion of the string in number and ask for *forgiveness* if we encounter an error (by using the `except`).\n",
"- Or we can test if the string is a number, using for example `str.isdigit()` or `str.isdecimal()` (*asking for permission*) and do the conversion only in this case.\n",
"\n",
"Both approches will lead to the same result so it is rather a question of principle. In Python, it is generally prefered to use `try` and `except` to follow the EAFP principle.\n",
"In this particular case, using `try` and `except` is far easier !"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"celltoolbar": "Slideshow",
"celltoolbar": "Diaporama",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
...
...
@@ -2623,18 +2640,18 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.2"
"version": "3.6.8"
},
"pycharm": {
"stem_cell": {
"cell_type": "raw",
"source": [],
"metadata": {
"collapsed": false
}
},
"source": []
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
\ No newline at end of file
}
%% Cell type:markdown id: tags:
# Python training UGA 2017
**A training to acquire strong basis in Python to use it efficiently**
Pierre Augier (LEGI), Cyrille Bonamy (LEGI), Eric Maldonado (Irstea), Franck Thollard (ISTerre), Christophe Picard (LJK), Loïc Huder (ISTerre)
# Standard types and basic statements
%% Cell type:markdown id: tags:
## Function calls
There are [built-in functions](https://docs.python.org/3/library/functions.html) and the developers can of course define other functions. To call a function:
Remark: `int` in Python 3 are impressive! No limit! See https://docs.python.org/3.1/whatsnew/3.0.html#integers
%% Cell type:markdown id: tags:
## Arithmetic operations
%% Cell type:code id: tags:
``` python
print(10+3)
print(10-3)
print(10*3)
print(10/3)# float division
print(10//3)# integer division
print(10%3)
```
%%%% Output: stream
13
7
30
3.3333333333333335
3
1
%% Cell type:markdown id: tags:
### `bool` (booleans)
%% Cell type:code id: tags:
``` python
b=bool('1')
b=False
b=True
```
%% Cell type:markdown id: tags:
##### Comparison operations (bool)
-`==` equal
-`!=` différent
-`<` inferior
-`<=` inferior or equal
-`>` superior
-`>=` superior or equal
%% Cell type:markdown id: tags:
##### Keyword `is`: check identity
%% Cell type:code id: tags:
``` python
a=None
print(aisNone)
print(aisnotNone)
```
%%%% Output: stream
True
False
%% Cell type:markdown id: tags:
##### Keywords `and` and `or`
%% Cell type:code id: tags:
``` python
TrueandTrue
```
%%%% Output: execute_result
True
%% Cell type:code id: tags:
``` python
TrueandFalse
```
%%%% Output: execute_result
False
%% Cell type:code id: tags:
``` python
FalseandFalse
```
%%%% Output: execute_result
False
%% Cell type:code id: tags:
``` python
TrueorTrue
```
%%%% Output: execute_result
True
%% Cell type:code id: tags:
``` python
TrueorFalse
```
%%%% Output: execute_result
True
%% Cell type:code id: tags:
``` python
FalseorFalse
```
%%%% Output: execute_result
False
%% Cell type:markdown id: tags:
### `float` (real, double precision) and `complex`
%% Cell type:code id: tags:
``` python
# float
a=float('1')
a=1.234
a=1e2
a=-1e-2
a=.2
```
%% Cell type:code id: tags:
``` python
# complex (2 floats)
c=complex('1')
c=1+2j
print(c,c.real,c.imag)
```
%%%% Output: stream
(1+2j) 1.0 2.0
%% Cell type:markdown id: tags:
Remark: notation `var_name.attr_name` to access to an attribute of an object.
%% Cell type:markdown id: tags:
## Warning about floating-point arithmetic and numerical errors!
%% Cell type:code id: tags:
``` python
b=1e16
c=1.2+b
d=c-b
print(d)
```
%%%% Output: stream
2.0
%% Cell type:markdown id: tags:
Very general issue (not Python):
See https://en.wikipedia.org/wiki/Floating-point_arithmetic and https://docs.python.org/3/tutorial/floatingpoint.html
%% Cell type:markdown id: tags:
### Standard type `str`
%% Cell type:code id: tags:
``` python
s='hello'
s="hello"
s=('How is it possible to write a very very '
'very long string with lines limited to 79 characters?')
s="""Strings on
more thand
one line.
"""
print(s)
```
%%%% Output: stream
Strings on
more thand
one line.
%% Cell type:markdown id: tags:
Warning: big difference between Python 2 and Python 3. In Python 3, `str` are unicode and there is another type `bytes`.
%% Cell type:markdown id: tags:
#### Methods of the type `str`
Objects of built-in types have methods associated with their type (object oriented programming). The built-in function `dir` returns a list of name of the attributes. For a string, these attributes are python system attributes (with double-underscores) and several public methods:
Very general, can be used on all sequences as `str`, `list`, etc... Not simple for beginners but very powerfull (see [here](http://stackoverflow.com/questions/509211/explain-pythons-slice-notation) and [here](http://avilpage.com/2015/03/a-slice-of-python-intelligence-behind.html)).
Python indexes and slices for a six-element str. Indexes enumerate the elements, slices enumerate the spaces between the elements.
```text
Index from rear: -6 -5 -4 -3 -2 -1
Index from front: 0 1 2 3 4 5
+---+---+---+---+---+---+
| a | b | c | d | e | f |
+---+---+---+---+---+---+
Slice from front: 0 1 2 3 4 5 6
Slice from rear: -6 -5 -4 -3 -2 -1 None
```
%% Cell type:code id: tags:
``` python
s = 'abcdef'
# s[start:stop:step]
s[2:6:2]
```
%%%% Output: execute_result
'ce'
%% Cell type:code id: tags:
``` python
# s[start:stop]
s[2:6]
```
%%%% Output: execute_result
'cdef'
%% Cell type:code id: tags:
``` python
# s[start:]
s[1:]
```
%%%% Output: execute_result
'bcdef'
%% Cell type:code id: tags:
``` python
# s[:stop]
s[:2]
```
%%%% Output: execute_result
'ab'
%% Cell type:code id: tags:
``` python
# step = -1: goes through the string in reverse order
s[::-1]
```
%%%% Output: execute_result
'fedcba'
%% Cell type:markdown id: tags:
### Do it yourself
Suppose we have a string representing a header line of the form:
%% Cell type:code id: tags:
``` python
s = ' wind;temperature;;pressure '
```
%% Cell type:markdown id: tags:
- Remove leading and ending blanks (see `str.replace` and `str.strip`)
- Extract the first field (e.g. using `find` method and slicing)
- Extract the last field (e.g. using `rfind` method and slicing)
- Check for empty field (e.g. `find` ";;" pattern)
- Remove empty field (e.g. using replace method)
- BONUS : Extract the second field (tip :`find` can take an argument that tells where to start the search)
%% Cell type:markdown id: tags:
#### A possible solution:
%% Cell type:code id: tags:
``` python
s = ' wind;temperature;;pressure '
# remove leading blanks
s = s.strip()
print("--{}--".format(s))
# extract the first field
idx = s.find(";")
s0 = s[0:idx]
print(s0)
# extract the second field
idx1 = s.find(";", idx+1) # start the search after the first ";"
s1 = s[idx+1:idx1]
print(s1)
# extract the last field
idx2 = s.rfind(";")
s2 = s[idx2+1:]
print(s2)
idx_first_empty_field = s.find(";;")
print(idx_first_empty_field)
# remove empty field
s_no_empty = s.replace(";;", ";")
print(s_no_empty)
```
%%%% Output: stream
--wind;temperature;;pressure--
wind
temperature
pressure
16
wind;temperature;pressure
%% Cell type:markdown id: tags:
### standard type `list`
A list is a **mutable sequence of (possibly inhomogeneous) elements**.
%% Cell type:code id: tags:
``` python
type([0, 'a'])
```
%%%% Output: execute_result
list
%% Cell type:code id: tags:
``` python
# create an empty list
l = []
# fill the list (with the function append)
l.append('2')
# fill the list (with the function extend)
l.extend([6, 3.])
print(l)
```
%%%% Output: stream
['2', 6, 3.0]
%% Cell type:code id: tags:
``` python
# concatenate lists with the operator +
print(l + ['hello', 3])
```
%%%% Output: stream
['2', 6, 3.0, 'hello', 3]
%% Cell type:code id: tags:
``` python
# get values
print(l[0], l[2], l[-2])
# slicing
print(l[0:2])
```
%%%% Output: stream
2 3.0 6
['2', 6]
%% Cell type:markdown id: tags:
### standard type `tuple`
A tuple is a **immutable sequence of (possibly inhomogeneous) elements**.
Remark: when you need a sequence that won't be modified, tuple is usually more efficient than list.
%% Cell type:code id: tags:
``` python
t = 0, 'a', 1.2
t1 = (5, 'hello')
t2 = tuple([1.1, 2])
type(t)
```
%%%% Output: execute_result
tuple
%% Cell type:code id: tags:
``` python
t[1] # indexing
```
%%%% Output: execute_result
'a'
%% Cell type:code id: tags:
``` python
t[1:] # slicing
```
%%%% Output: execute_result
('a', 1.2)
%% Cell type:code id: tags:
``` python
a, b = t1 # tuple assigment
print(b)
```
%%%% Output: stream
hello
%% Cell type:markdown id: tags:
## Mutable and immutable objects
The objects of type `str`, `int`, `float`, `bool` are immutable. They can not be modified. Of course, a name that points towards an integer can point towards a different integer.
%% Cell type:code id: tags:
``` python
i = 1
i = i + 2 # (or i += 2)
print(i)
i = 10
print(i)
```
%%%% Output: stream
3
10
%% Cell type:markdown id: tags:
Here, the objects `1` and `3` have not been modified.
%% Cell type:markdown id: tags:
## Mutable and immutable objects
An object of type `list` is mutable:
%% Cell type:code id: tags:
``` python
l = [0, 5]
print(l)
l.append('hello')
print(l)
```
%%%% Output: stream
[0, 5]
[0, 5, 'hello']
%% Cell type:markdown id: tags:
Here, the object list tagged by the name `l` has been modified inplace.
%% Cell type:markdown id: tags:
## References and `del` keyword
`del` removes a reference. If an object in not binded to any names, Python can delete it from its internal memory.
%% Cell type:code id: tags:
``` python
l = ['a', 'b']
del l[1]
print(l)
```
%%%% Output: stream
['a']
%% Cell type:markdown id: tags:
### More on slicing
Very general, can be used on all sequences as `str`, `list`, etc... Not simple for beginners but very powerfull (see [here](http://stackoverflow.com/questions/509211/explain-pythons-slice-notation) and [here](http://avilpage.com/2015/03/a-slice-of-python-intelligence-behind.html)).
Python indexes and slices for a six-element str. Indexes enumerate the elements, slices enumerate the spaces between the elements.
```text
Index from rear: -6 -5 -4 -3 -2 -1
Index from front: 0 1 2 3 4 5
+---+---+---+---+---+---+
| a | b | c | d | e | f |
+---+---+---+---+---+---+
Slice from front: 0 1 2 3 4 5 6
Slice from rear: -6 -5 -4 -3 -2 -1 0
```
%% Cell type:code id: tags:
``` python
s = 'abcdef'
# s[start:stop:step]
s[2:6:2]
```
%%%% Output: execute_result
'ce'
%% Cell type:markdown id: tags:
### More on slicing
#### Assigment to mutable object
%% Cell type:code id: tags:
``` python
l = [0, 1, 2, 3, 4, 5]
l1 = l # assigment to a new name l1 (no copy of the object).
# the names l and l1 points towards the same object.
l1.append('a')
print(l1)
print(l)
```
%%%% Output: stream
[0, 1, 2, 3, 4, 5, 'a']
[0, 1, 2, 3, 4, 5, 'a']
%% Cell type:markdown id: tags:
#### Shallow copy
%% Cell type:code id: tags:
``` python
l = [0, 1, 2, 3, 4, 5]
l1 = l[:] # shallow copy of l
l1.append('a')
print(l1)
print(l)
```
%%%% Output: stream
[0, 1, 2, 3, 4, 5, 'a']
[0, 1, 2, 3, 4, 5]
%% Cell type:markdown id: tags:
### More on slicing
Other examples of slices for a six-element list. Indexes enumerate the elements, slices enumerate the spaces between the elements.
%% Cell type:code id: tags:
``` python
a = [0, 1, 2, 3, 4, 5]
all([
len(a) == 6,
a[1:] == [1, 2, 3, 4, 5],
a[:5] == [0, 1, 2, 3, 4],
a[0] == 0,
a[:-2] == [0, 1, 2, 3],
a[5] == 5,
a[1:2] == [1],
a[-1] == 5,
a[1:-1] == [1, 2, 3, 4],
a[-2] == 4,
])
```
%%%% Output: execute_result
True
%% Cell type:markdown id: tags:
### Do it yourself
Suppose we have the string containing header line.
%% Cell type:code id: tags:
``` python
s = 'wind;temperature;pressure'
```
%% Cell type:markdown id: tags:
- Extract the list of items (i.e. "wind", "temperature", "pressure"; see `str.split`).
- Add "Snow level" to the list of items (e.g. using append)
- Build a new header such that items are capitalized (e.g. using the methods `str.join` and `str.capitalize` and iterating on the list)
%% Cell type:markdown id: tags:
#### A possible solution:
%% Cell type:code id: tags:
``` python
s = 'wind;temperature;pressure'
list_items = s.split(";")
print(list_items)
list_items.append("snow level".capitalize())
list_items[0] = list_items[0].capitalize()
list_items[1] = list_items[1].capitalize()
list_items[2] = list_items[2].capitalize()
print(list_items)
";".join(list_items)
```
%%%% Output: stream
['wind', 'temperature', 'pressure']
['Wind', 'Temperature', 'Pressure', 'Snow level']
%%%% Output: execute_result
'Wind;Temperature;Pressure;Snow level'
%% Cell type:markdown id: tags:
### The function `range`
The function returns a range object:
%% Cell type:code id: tags:
``` python
# start, stop, step
range(1, 8, 2)
```
%%%% Output: execute_result
range(1, 8, 2)
%% Cell type:markdown id: tags:
We can make a list with the range object:
%% Cell type:code id: tags:
``` python
# start, stop, step
list(range(1, 8, 2))
```
%%%% Output: execute_result
[1, 3, 5, 7]
%% Cell type:code id: tags:
``` python
# start, stop (step=1)
list(range(2, 8))
```
%%%% Output: execute_result
[2, 3, 4, 5, 6, 7]
%% Cell type:code id: tags:
``` python
# stop argument (start=0, step=1)
list(range(8))
```
%%%% Output: execute_result
[0, 1, 2, 3, 4, 5, 6, 7]
%% Cell type:markdown id: tags:
### Do it yourself
Build a list of odd numbers in decreasing order.
%% Cell type:markdown id: tags:
## Conditions: `if`, `elif`, `else`
```python
if expression:
statement(s)
else:
statement(s)
```
The statement contains the block of code that executes if the conditional expression in the if statement resolves to 1 or a TRUE value.
%% Cell type:code id: tags:
``` python
a = 0
if a == 0:
print('a is equal to 0.')
```
%%%% Output: stream
a is equal to 0.
%% Cell type:code id: tags:
``` python
a = 1
if a < 0:
print('a is negative.')
elif a == 0:
print('a is equal to 0.')
elif a > 0:
print('a is positive.')
else:
print("I don't know.")
```
%%%% Output: stream
a is positive.
%% Cell type:markdown id: tags:
## Loops
%% Cell type:markdown id: tags:
### Loops with the keyword `while`
%% Cell type:code id: tags:
``` python
i = 0
while i < 4:
i += 1
print('i =', i)
```
%%%% Output: stream
i = 4
%% Cell type:code id: tags:
``` python
i = 0
while i < 4:
i += 1
print('i =', i)
```
%%%% Output: stream
i = 1
i = 2
i = 3
i = 4
%% Cell type:markdown id: tags:
### Do it yourself
- Edit a script with the spyder editor that calculates the average of a set of numbers. For example `numbers = [67, 12, 2, 9, 23, 5]`
* using the functions `sum` and `len`
* manually, using the keyword `while`
- Run the script
* in spyder,
* in a ipython session opened from another terminal,
For each line of this string, append a variable of correct type in a list (i.e. "hello" should stay hello,
2 should become an int and 1.5 a float). Do it by catching errors.
**Hints:**
- int("a") and float("a") raise ValueError
- the above str_variable can be split using "\n"
%% Cell type:code id: tags:
``` python
str_variables = """hello
1.5
2"""
the_list_you_should_get = ["hello", 1.5, 2]
```
%% Cell type:markdown id: tags:
#### A possible solution:
%% Cell type:code id: tags:
``` python
split_list = []
for value in str_variables.split("\n"):
try:
value = int(value)
except ValueError:
print(value, "is not a int")
try:
value = float(value)
except ValueError:
print(value, 'is not a float')
split_list.append(value)
print(split_list)
```
%%%% Output: stream
hello is not a int
hello is not a float
1.5 is not a int
['hello', 1.5, 2]
%% Cell type:markdown id: tags:
### Bonus: the Easier to Ask for Forgiveness than Permission (EAFP) principle
There are several ways to perform the previous task:
- In the solution presented above, we `try` first the conversion of the string in number and ask for *forgiveness* if we encounter an error (by using the `except`).
- Or we can test if the string is a number, using for example `str.isdigit()` or `str.isdecimal()` (*asking for permission*) and do the conversion only in this case.
Both approches will lead to the same result so it is rather a question of principle. In Python, it is generally prefered to use `try` and `except` to follow the EAFP principle.
In this particular case, using `try` and `except` is far easier !