**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)
# Functions
A function is a block of organized, reusable code that is used to perform a single, related action. Functions provide better modularity for your application and a high degree of code
reusing.
%% Cell type:markdown id: tags:
## Simple function definitions and calls
Function blocks begin with the keyword `def` followed by the function name and parentheses (`()`).
- The code block within every function starts with a colon (:) and is indented.
- Any input parameters or arguments should be placed within these parentheses.
%% Cell type:code id: tags:
``` python
defprint_hello():
"hello printer"
print('hello')
defmyprint(s):
"my hello printer"
print('I print',s)
# function calls
print_hello()
print_hello()
myprint('First call of myprint')
myprint('Second call of myprint')
```
%%%% Output: stream
hello
hello
I print First call of myprint
I print Second call of myprint
%% Cell type:markdown id: tags:
## Simple function definitions and calls
- The first statement of a function can be the documentation string of the function, also called "docstring".
- The statement `return [expression]` exits a function, optionally passing back an expression to the caller. No return statement or a return statement with no arguments is the same as `return None`.
(Note: Wikipedia about duck typing: https://fr.wikipedia.org/wiki/Duck_typing)
%% Cell type:code id: tags:
``` python
importunittest
defadd(arg0,arg1):
"""Print and return the sum of the two arguments (duck typing)."""
result=arg0+arg1
print('result = ',result)
returnresult
```
%% Cell type:code id: tags:
``` python
add(2,3)
```
%%%% Output: stream
result = 5
%%%% Output: execute_result
5
%% Cell type:code id: tags:
``` python
add('a','b')
```
%%%% Output: stream
result = ab
%%%% Output: execute_result
'ab'
%% Cell type:markdown id: tags:
### Do it yourself: simple function definition
Write a function that returns the sum of the first argument with twice the second argument.
%% Cell type:code id: tags:
``` python
importunittest
defadd_second_twice(arg0,arg1):
"""Return the sum of the first argument with twice the second one.
Arguments should be of type that support sum and product by
## All Python functions return exactly one object but... `None` and `tuple`
%% Cell type:code id: tags:
``` python
type(print())
```
%%%% Output: stream
%%%% Output: execute_result
NoneType
%% Cell type:code id: tags:
``` python
defreturn_a_tuple():
return1,'hello',3# a tuple, same as (1, 'hello', 3)
my_tuple=return_a_tuple()
print(my_tuple)
```
%%%% Output: stream
(1, 'hello', 3)
%% Cell type:code id: tags:
``` python
a,b,c=return_a_tuple()
print(b)
```
%%%% Output: stream
hello
%% Cell type:markdown id: tags:
## Function call: namespaces and objects "passed by references"
For each function call:
- a **new namespace** is created (as at the beginning of a module)
- the objects are **"passed by references"**: new names of the arguments are created in the function namespace and they point towards the objects given as arguments to the function (so it is possible to modify the mutable objects).
%% Cell type:markdown id: tags:
## Function call: objects "passed by references"
Exercice: use 2 schemes "namespaces-objects" to understand these 2 pieces of code.
%% Cell type:code id: tags:
``` python
number=2
mylist=[]
defmy_strange_append_square(l,n):
# new function namespace with names "l" and "n"
n=n**2
l.append(n)
my_strange_append_square(mylist,number)
print(mylist,number)
```
%%%% Output: stream
[4] 2
%% Cell type:code id: tags:
``` python
number=2
mylist=[]
defmy_strange_append_square(mylist,number):
# new function namespace with names "mylist" and "number"
number=number**2
mylist.append(number)
my_strange_append_square(mylist,number)
print(mylist,number)
```
%%%% Output: stream
[4] 2
%% Cell type:markdown id: tags:
## Global vs Local variables
Variables that are defined inside a function body have a local scope (i.e. are defined in the function namespace), and those defined outside have a global scope.
This means that local variables can be accessed only inside the function in which they are declared, whereas global variables can be accessed throughout the module by all functions.
%% Cell type:code id: tags:
``` python
# global variables
result=0
multiplicator=2
defmultiply(arg0):
# here we create a new name `result` in the function namespace
# `result` is a local variable
# we can use the global variable `multiplicator`
result=multiplicator*arg0
print('Inside the function local result:\t',result)
returnresult
multiply(10)
print('Outside the function global result:\t',result)
```
%%%% Output: stream
Inside the function local result: 20
Outside the function global result: 0
%% Cell type:markdown id: tags:
- Global variables can be used in a function.
- Global variables can not be modified in a function (except with the `global` keyword. Discourage!).
%% Cell type:markdown id: tags:
## Global vs Local variables: `global` keyword
There is a keyword `global` to define inside a function a global variable and to modify a global variable in the function. **It is often a bad idea to use it :-)**
%% Cell type:code id: tags:
``` python
deffunc():
globalme
# Defined locally but declared as global
me='global variable locally defined'
print(me)
func()
# Ask for a global variable
print(me)
```
%%%% Output: stream
global variable locally defined
global variable locally defined
%% Cell type:code id: tags:
``` python
delta=0
defadd_1_to_delta():
globaldelta
# global variable modified in a function
delta+=1
foriinrange(4):
add_1_to_delta()
print(delta,end=', ')
```
%%%% Output: stream
1, 2, 3, 4,
%% Cell type:markdown id: tags:
## Function Arguments
You can call a function by using the following types of formal arguments:
- Required arguments
- Keyword arguments
- Default arguments
- Variable-length arguments
%% Cell type:markdown id: tags:
### Required arguments
Required arguments are the arguments passed to a function in correct positional order. Here, the number of arguments in the function call should match exactly with the function definition.
%% Cell type:code id: tags:
``` python
defmyfunc(arg0,arg1):
"Return the sum of the first argument with twice the second one."
To call the function `myfunc`, you definitely need to pass two arguments, otherwise it gives a syntax error.
%% Cell type:markdown id: tags:
### Keyword arguments
Keyword arguments are related to the function calls. When you use keyword arguments in a function call, Python identifies the arguments by the parameter name.
%% Cell type:code id: tags:
``` python
myfunc(arg1=3,arg0=2)
```
%%%% Output: stream
arg0 + 2*arg1 = 2 + 2*3 = 8
%%%% Output: execute_result
8
%% Cell type:markdown id: tags:
### Default arguments
A default argument is an argument that assumes a default value if a value is not provided in the function call for that argument.
%% Cell type:code id: tags:
``` python
defmyfunc1(arg0,arg1=None):
"Return the sum of the first argument with twice the second one."
ifarg1isNone:
iftype(arg0)==int:
arg1=0
else:
arg1=""
myfunc(arg0,arg1)
myfunc1("a","n")
```
%%%% Output: stream
arg0 + 2*arg1 = a + 2*n = ann
%% Cell type:code id: tags:
``` python
myfunc1(1,3)
```
%%%% Output: stream
arg0 + 2*arg1 = 1 + 2*3 = 7
%% Cell type:markdown id: tags:
### Default arguments
**Warning:** the default arguments are created only once, at the function definition! They are stored in a tuple associated with the function object.
You may need to process a function for more arguments than you specified while defining the function. These arguments are called variable-length arguments and are not named in the function definition, unlike required and default arguments.
An asterisk (*) is placed before the variable name that holds the values of all nonkeyword variable arguments.
%% Cell type:code id: tags:
``` python
defsum_args(*args):
"""Return the sum of numbers."""
totalsum=0
print('args =',args)
forvarinargs:
totalsum+=var
print('totalsum =',totalsum)
returntotalsum
sum_args()
sum_args(4)
sum_args(4,3,4,7)
```
%%%% Output: stream
args = ()
totalsum = 0
args = (4,)
totalsum = 4
args = (4, 3, 4, 7)
totalsum = 18
%%%% Output: execute_result
18
%% Cell type:markdown id: tags:
### Variable-length arguments
There is also a (very useful) syntax with two asterisks `**`, which works like this:
Write a function that takes as input a list `l` and a number `a` and that multiplies
all the elements of the list by the number. If not set, number is defaulted to 2.
%% Cell type:markdown id: tags:
#### A possible solution:
%% Cell type:code id: tags:
``` python
deffunc(l,a=2):
fori,valinenumerate(l):
l[i]=a*val
l=list(range(3))
print(l)
func(l)
print(l)
func(l,4)
print(l)
l=['a','b']
func(l,4)
print(l)
```
%%%% Output: stream
[0, 1, 2]
[0, 2, 4]
[0, 8, 16]
['aaaa', 'bbbb']
%% Cell type:markdown id: tags:
## `lambda` keyword and anonymous functions
These functions are called anonymous because they are not declared by using the `def` keyword but with the `lambda` keyword so they have not name.
- Lambda forms can take any number of arguments but return just one value in the form of an expression. They cannot contain commands or multiple expressions.
- Lambda form is used in functional programming (but it is usually better to use list comprehension) and for [callbacks in GUI](https://pythonconquerstheuniverse.wordpress.com/2011/08/29/lambda_tutorial/).