06_functions
06_functions
"""06_functions.ipynb
# Functions
input_num = "44"
print(str(int(input_num) + 2))
# the use of str() is not compulsory in print, since all arguments
are automatically transformed into string before visualizing on the
console
print(int(input_num) + 2)
```python
def name_of_function([<list of comma-separated
parameters>]): # the list can be empty
< indented block of statements >
....
def print_my_strings():
msg = "Hello!"
print(msg)
print("How are you from 0 to 10?")
# %who
print_twice("aa", "bb")
print(n)
# %lsmagic
This execution scheme works well even if the called function calls
another, and so on.
Python is good at keeping track of where the flow of execution is,
moving forward and backward between different functions.
In summary, when you read a program, you don't always want to read
from top to bottom. Sometimes it makes more sense if you follow the
flow of execution. Use [Python tutor](https://pythontutor.com/) to
visualize the execution of a program with function definitions and
function calls.
def foo(val):
incr = 12
a = 10
val = val + incr + a + 10
print("local variable:", val)
a = 20
incr = 1000
foo(8)
"""
def foo1():
c = a + 1 # access varial a, located in the global space
# a = c + 1 # in general, you cannot change variables in the
global namespaces
print("local variable: ", c)
a = 15
foo1()
print(a)
In the following example the same name `a` is used in the local and
global namespace. Within the function, we access to the variable in
the local namespace, whereas the variable in the global namespace is
left unmodified.
```python
def b():
a = c + 1
print('local namespace', a)
a = 12
c = 13
b()
print('global namespace', a)
```
"""
def b():
#global a
a = c + 1
print('global namespace', c)
print('local namespace', a)
#print('global namespace', a)
a = 12
c = 13
b()
print('global namespace', a)
When you define a function you can specify a default value for one
or more arguments. This creates a function that can be called with
fewer arguments.
"""
print_twice('Hello')
print_twice('Ciao')
print_twice('Hello', param2="Giovanni!", param3 = 'How old are
you?')
print_twice('Hello', param2="Giovanni!")
print_twice('Ciao', param3="Come stai?")
"""# Docstrings
```python
def fib(n):
'''
Print a Fibonacci series up to n, n>=0.
example for n=35: 0,1,1,2,3,5,8,13,21,34
Args:
n: limit of the value to include in the series, n>=0.
Returns:
No return value, but print the list.
'''
if n == 0:
print(0) # first Fibonacci value
elif n >= 1:
print(0, 1, 1, end=' ') # first three Fibonacci
values
next = 2 # new Fib value (to print)
previous = 1 # previous Fib value (already printed)
while next <= n:
print(next, end=' ')
new_next = next + previous # store in "new_next"
the next Fib value (to print in the next iteration)
print()
```
def fib(n):
'''
Print a Fibonacci series up to n, n>=0.
example for n=35: 0,1,1,2,3,5,8,13,21,34
Args:
n: limit of the value to include in the series (n >= 0).
Returns:
No return value, but print the list.
'''
if n == 0:
print(0) # first Fibonacci value
elif n >= 1:
print(0, 1, 1, end=' ') # first three Fibonacci values
next = 2 # new Fib value (to print)
previous = 1 # previous Fib value (already printed)
while next <= n:
print(next, end=' ')
new_next = next + previous # store in "new_next" the next Fib
value (to print in the next iteration)
# fib
fib(1000)
But the above functions are all **void**: they have an effect, as
they print values, but they do not have a return value. How can we
write **fruitful** functions?
```python
def area(radius):
a = 3.14 * radius**2
return a
```
"""
import math
def area_square(side):
a = side**2
return a
def area_circle(radius):
a = math.pi * area_square(radius) #radius**2
return a
$$
0! = 1\\
n! = n \cdot (n - 1)!
$$
This definition says that the factorial of $0$ is $1$, and the
factorial of any other value, $n$, is $n$
multiplied by the factorial of $n - 1$.
So $3!$ is $3$ times $2!$, which is $2$ times $1!$, which is $1$
times $0!$. $0!$ is the base case, where the definition is known.
The first step is to decide what the parameters should be. In this
case it should
be clear that factorial takes an integer:
```python
def factorial(n):
```
If the argument happens to be 0, all we have to do is to return 1,
otherwise we have to make a **recursive call** to find the
factorial of $n - 1$ and then multiply it by $n$:
```python
def factorial(n):
if n == 0:
return 1
else:
recurse = factorial(n-1)
result = n * recurse
return result
```
Since $3$ is not $0$, we take the second branch and calculate the
factorial of $n-1$ (which is $2$)...<br/>
Since $2$ is not $0$, we take the second
branch and calculate the factorial of $n-1$ (which is $1$)...<br/>
Since $1$ is not
$0$, we take the second branch and calculate the factorial
of $n-1$ (which is $0$)...<br/>
&n
bsp;Since $0$ equals $0$, we take the first branch and return $1$
without making any more recursive calls.<br/>
The return value,
$1$, is multiplied by $n$, which is $1$, and the result is
returned.<br/>
The return value, $1$, is multiplied by $n$,
which is $2$, and the result is returned.<br/>
The return value ($2$) is multiplied by $n$, which is $3$, and the
result, $6$, becomes the return
value of the function call that started the whole process.
```python
result = factorial(3)
```
"""
def factorial(n):
if n == 0:
return 1
else:
recurse = factorial(n-1)
result = n * recurse
return result
print(factorial(4))
The return values are shown being passed back up the stack. In each
frame, the return value is the value of `result`, which is the
product of $n$ and `recurse`.
In the last frame, the local variables `recurse` and `result` do not
exist, because the branch that creates them does not run.
# Exercises
def check_prime(n):
'''
Return True if the input argument n is prime, False otherwise
Args:
n: integer to be checked.
Returns:
Boolean value.
'''
is_prime = True
return is_prime
# 𝑓𝑖𝑏(0) = 0
# 𝑓𝑖𝑏(1) = 1
# 𝑓𝑖𝑏(𝑛) = 𝑓𝑖𝑏(𝑛−1)+𝑓𝑖𝑏(𝑛−2)
# recursive
def recfib(n):
'''
Print the n-th element of the Fibonacci series (counting from 0)
Args:
n: n-th position in the Fibonacci series.
Returns:
Value of the item in the series at position n.
'''
if n == 0:
return 0
if n == 1:
return 1
return recfib(n-2) + recfib(n-1)
for i in range(20):
print(recfib(i), end=' ')
# 𝑠𝑢𝑚_𝑙𝑖𝑠𝑡(𝑙,𝑙) = 𝑙
# 𝑠𝑢𝑚_𝑙𝑖𝑠𝑡(𝑙,𝑢) = 𝑙 + 𝑠𝑢𝑚_𝑙𝑖𝑠𝑡(𝑙+1,𝑢)
def sum_list(l,u):
'''
Compute and return the sum of the integers x, where l <= x <= u.
Args:
l: lower bound of the series
u: upper bound of the series
requirement: l <= u
Returns:
Sum of the subseries.
'''
if l > u:
s = 0
elif l == u:
s = l
else:
s = l + sum_list(l+1,u)
return s
def sum_list_norec(l,u):
if l > u:
return 0
s = 0
for item in range(l,u+1):
print("-->", item)
s = s + item
return s
print(sum_list(6,5))
print(sum_list(5,5))
print(sum_list(5,10), 10*11/2 - 4*5/2)
print("\n", 6, 5, "*****")
print(sum_list_norec(6,5))
print("\n", 5, 5, "*****")
print(sum_list_norec(5,5))