Skip to content
Snippets Groups Projects
Commit 287f490d authored by Ulrich Kerzel's avatar Ulrich Kerzel
Browse files

add comments to account solution whre to improve more

parent c7cbbf75
No related branches found
No related tags found
No related merge requests found
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": 2,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -69,7 +69,7 @@ ...@@ -69,7 +69,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": 3,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
...@@ -362,7 +362,7 @@ ...@@ -362,7 +362,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.10.6" "version": "3.10.12"
}, },
"orig_nbformat": 4, "orig_nbformat": 4,
"vscode": { "vscode": {
......
...@@ -150,7 +150,7 @@ ...@@ -150,7 +150,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.10.6" "version": "3.10.12"
}, },
"orig_nbformat": 4, "orig_nbformat": 4,
"vscode": { "vscode": {
......
...@@ -169,7 +169,7 @@ ...@@ -169,7 +169,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.10.6" "version": "3.10.12"
}, },
"orig_nbformat": 4, "orig_nbformat": 4,
"vscode": { "vscode": {
......
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# Functions # Functions
We could - in principle - write code by adding more and more statements after one another. This might well work and do what we want, but would have quite some disadvantages. We could - in principle - write code by adding more and more statements after one another. This might well work and do what we want, but would have quite some disadvantages.
* The code becomes very long very quickly ("Spaghetti - Code") * The code becomes very long very quickly ("Spaghetti - Code")
* We would need to keep track of *a lot* of variables as each variable is valid all the time. * We would need to keep track of *a lot* of variables as each variable is valid all the time.
* The only way to re-use code is to copy/paste it. * The only way to re-use code is to copy/paste it.
It works... but it is neither nice, efficient, readable or maintainable. It works... but it is neither nice, efficient, readable or maintainable.
Functions help us to structure code. Essentially, they assign a block of code to a call of this function. Functions help us to structure code. Essentially, they assign a block of code to a call of this function.
The general structure is: The general structure is:
``` ```
def my_func(<arguments>): def my_func(<arguments>):
.... ....
my code goes here my code goes here
.... ....
return <return value> return <return value>
``` ```
We notice the following: We notice the following:
* The function is defined using the keyword ```def``` * The function is defined using the keyword ```def```
* The name of the function is given by ```my_func``` * The name of the function is given by ```my_func```
* We can pass ```<arguments>``` arguments to the function, This is optional. * We can pass ```<arguments>``` arguments to the function, This is optional.
* Functions can have one or multiple return value(s), indicated by the keyword ```return```. This is optional. * Functions can have one or multiple return value(s), indicated by the keyword ```return```. This is optional.
Some programming languages distinguish between functions that return a value ("functions") or not ("procedures"). Python does not and we call them all "functions". Some programming languages distinguish between functions that return a value ("functions") or not ("procedures"). Python does not and we call them all "functions".
Therefore, the simplest function is something like the following: Therefore, the simplest function is something like the following:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# define the function # define the function
def say_hello(): def say_hello():
print("This is a small function that says Hello.") print("This is a small function that says Hello.")
# call the function # call the function
say_hello() say_hello()
``` ```
%% Output %% Output
This is a small function that says Hello. This is a small function that says Hello.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
This is probably not the most useful function we can think of - but it allows us to see what we can do: This is probably not the most useful function we can think of - but it allows us to see what we can do:
* We can assign a descriptive name to a block of code. The name should give a short indication about what the function does so that when reading the code we can follow what happens. * We can assign a descriptive name to a block of code. The name should give a short indication about what the function does so that when reading the code we can follow what happens.
* We can re-use the code. Whenever we want to execute the same block of code, we call the function. This makes it much easier to write understandable and efficient code - and also helps us to maintain the code. Whenever we find a bug, we need to fix it only in this function. * We can re-use the code. Whenever we want to execute the same block of code, we call the function. This makes it much easier to write understandable and efficient code - and also helps us to maintain the code. Whenever we find a bug, we need to fix it only in this function.
***Best practice*** ***Best practice***
Functions should only do one thing. This makes them as short, concise and efficient as possible. It also makes them testable (we know what to expect as output), and more maintainable. Functions should only do one thing. This makes them as short, concise and efficient as possible. It also makes them testable (we know what to expect as output), and more maintainable.
While there is an overhead in calling a function, it is *very* small compared to writing inefficient and lengthy code. Do not hesitate to put even a single line of code into a separate function if you think that this will help to make the code easier to read, debug and maintain. While there is an overhead in calling a function, it is *very* small compared to writing inefficient and lengthy code. Do not hesitate to put even a single line of code into a separate function if you think that this will help to make the code easier to read, debug and maintain.
## Function arguments ## Function arguments
Functions can have one or more arguments that we pass when calling the function. Functions can have one or more arguments that we pass when calling the function.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def my_sum(x, y): def my_sum(x, y):
return x + y print(type(x), type(y))
return x +y, x, y
sum = my_sum(3,4) sum, a ,b = my_sum(3,4)
print('The sum is: {}'.format(sum)) print('The sum is: {} {} {}'.format(sum,a,b))
``` ```
%% Output %% Output
The sum is: 7.1 <class 'int'> <class 'int'>
The sum is: 7 3 4
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
We can make use of the arguments in several ways: Above we pass two numbers and naturally assume that $x=3, y=4$ when we compute the sum. Here, the order of the variables and the arguments matter. The variables are assigned in the order we pass them. We can make use of the arguments in several ways: Above we pass two numbers and naturally assume that $x=3, y=4$ when we compute the sum. Here, the order of the variables and the arguments matter. The variables are assigned in the order we pass them.
We can also specify this explicity. We can also specify this explicity.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def my_sum(x, y): def my_sum(x, y):
print('x={}, y={}'.format(x,y)) print('x={}, y={}'.format(x,y))
return x + y return x + y
sum = my_sum(y=4, x=3) sum = my_sum(y=4, x=3)
print('The sum is: {}'.format(sum)) print('The sum is: {}'.format(sum))
``` ```
%% Output %% Output
x=3, y=4 x=3, y=4
The sum is: 7 The sum is: 7
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Here, we specify the variables directly and can choose any order. Here, we specify the variables directly and can choose any order.
We can also define default arguments, i.e. a value, that is taken when we do not specify the variable. We can also define default arguments, i.e. a value, that is taken when we do not specify the variable.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def my_sum(x=3, y=4): def my_sum(x=3, y=4):
print('x={}, y={}'.format(x,y)) print('x={}, y={}'.format(x,y))
return x + y return x + y
sum = my_sum() sum = my_sum()
print('The sum is: {}'.format(sum)) print('The sum is: {}'.format(sum))
sum = my_sum(1) sum = my_sum(1)
print('The sum is: {}'.format(sum)) print('The sum is: {}'.format(sum))
sum = my_sum(2,6) sum = my_sum(2,6)
print('The sum is: {}'.format(sum)) print('The sum is: {}'.format(sum))
sum = my_sum(x=2) sum = my_sum(x=2)
print('The sum is: {}'.format(sum)) print('The sum is: {}'.format(sum))
sum = my_sum(x=2, y=1) sum = my_sum(x=2, y=1)
print('The sum is: {}'.format(sum)) print('The sum is: {}'.format(sum))
``` ```
%% Output %% Output
x=3, y=4 x=3, y=4
The sum is: 7 The sum is: 7
x=1, y=4 x=1, y=4
The sum is: 5 The sum is: 5
x=2, y=6 x=2, y=6
The sum is: 8 The sum is: 8
x=2, y=4 x=2, y=4
The sum is: 6 The sum is: 6
x=2, y=1 x=2, y=1
The sum is: 3 The sum is: 3
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
There are a (very) few use-cases where you do not know how many arguments a user will pass. We can do this by preceeding the variable name in the argument list with a single ```*```. There are a (very) few use-cases where you do not know how many arguments a user will pass. We can do this by preceeding the variable name in the argument list with a single ```*```.
***Note*** ***Note***
These arguments are often abbreviated as ```*args```, as we do not know what they will be. These arguments are often abbreviated as ```*args```, as we do not know what they will be.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def print_pets(*args): def print_pets(*args):
print(args) print(args)
print('dog') print('dog')
print('dog', 'cat') print('dog', 'cat')
print('dog', 'cat', 'hamster') print('dog', 'cat', 'hamster')
``` ```
%% Output %% Output
dog dog
dog cat dog cat
dog cat hamster dog cat hamster
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Sometimes, we might want to use a function with an arbitrary number of arguments and we also do not know what kind of information is going to be passed. We can use the ```**``` construct to accept as many key-value pairs as are provided. Sometimes, we might want to use a function with an arbitrary number of arguments and we also do not know what kind of information is going to be passed. We can use the ```**``` construct to accept as many key-value pairs as are provided.
An example could be: An example could be:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def update_userprofile(name, **profile): def update_userprofile(name, **profile):
profile['name'] = name profile['name'] = name
return profile return profile
user_profile = update_userprofile('Reynolds', user_profile = update_userprofile('Reynolds',
first_name = 'Malcom', first_name = 'Malcom',
rank = 'Captain', rank = 'Captain',
gender = 'male') gender = 'male')
print(user_profile) print(user_profile)
``` ```
%% Output %% Output
{'first_name': 'Malcom', 'rank': 'Captain', 'gender': 'male', 'name': 'Reynolds'} {'first_name': 'Malcom', 'rank': 'Captain', 'gender': 'male', 'name': 'Reynolds'}
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
As we can see, the ```**profile``` creates a dictionary into which we (implicitly) add all the key-value pairs we pass as arguments to the function. As we can see, the ```**profile``` creates a dictionary into which we (implicitly) add all the key-value pairs we pass as arguments to the function.
Inside the function, we can access and change the dictionary as we normally would (e.g. add a new field with key ```name```). Inside the function, we can access and change the dictionary as we normally would (e.g. add a new field with key ```name```).
As we can also see, this makes the code less readable and - because we do not know what the user will pass to the function - we also would not know how to check whether this was intentional, etc. As we can also see, this makes the code less readable and - because we do not know what the user will pass to the function - we also would not know how to check whether this was intentional, etc.
One good use-case for such a construct is that we want to use a generic way to pass options to our code, such as keyword arguments. One good use-case for such a construct is that we want to use a generic way to pass options to our code, such as keyword arguments.
In general, when we find ourselves in the situation to need such constructs with ```*``` or ```**```, we should take the opportunity to reflect if we really need this and if we can use simpler approaches to make our code more readable and maintainable. In general, when we find ourselves in the situation to need such constructs with ```*``` or ```**```, we should take the opportunity to reflect if we really need this and if we can use simpler approaches to make our code more readable and maintainable.
## Local variables ## Local variables
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def my_function(x, y): def my_function(x, y):
i = 0 i = 0
print('The value of i is {}'.format(i)) print('The value of i is {}'.format(i))
return x + y return x + y
sum = my_function(3, 4) sum = my_function(3, 4)
# uncommenting this will fail. # uncommenting this will fail.
# print('The value of i is {}'.format(i)) # print('The value of i is {}'.format(i))
``` ```
%% Output %% Output
The value of i is 0 The value of i is 0
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
So far, all variables we have used in our code, inside or outside loops are always available: Once we have used a variable, it is defined and the Python interpreter keeps it in memory. This is our ***global*** scope. So far, all variables we have used in our code, inside or outside loops are always available: Once we have used a variable, it is defined and the Python interpreter keeps it in memory. This is our ***global*** scope.
As our example above shows, variables that we use inside a function are only valid within this function, a ***local*** scope. As our example above shows, variables that we use inside a function are only valid within this function, a ***local*** scope.
This has the benefit that we can define the variables we need inside the function and we do not need to clean up afterwards. Again, this makes the code more readable and maintainable, as we can move blocks of code *together with the relevant variables* into a function. This has the benefit that we can define the variables we need inside the function and we do not need to clean up afterwards. Again, this makes the code more readable and maintainable, as we can move blocks of code *together with the relevant variables* into a function.
***Best practice*** ***Best practice***
When defining a function, do not rely on global variables defined outside the scope of this function. Instead, all variables that you need inside the function should be passed as arguments, all variables that you need back, should be part of the ```return``` statement. When defining a function, do not rely on global variables defined outside the scope of this function. Instead, all variables that you need inside the function should be passed as arguments, all variables that you need back, should be part of the ```return``` statement.
The following works but is clearly not a good idea: The following works but is clearly not a good idea:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
sum = 0 sum = 0
x = 3 x = 3
y = 7 y = 7
def stupid_sum(): def stupid_sum():
global sum global sum
sum = x + y sum = x + y
stupid_sum() stupid_sum()
print('The sum is {}'.format(sum)) print('The sum is {}'.format(sum))
``` ```
%% Output %% Output
The sum is 10 The sum is 10
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Here, we use the keyword ```global``` to force Python to make use of the variable ```sum``` defined outside the function such that it modifies this variable (otherwise, a local variable would be created with the same name, but not returned. ---try it by commenting out line with ```global sum```). Here, we use the keyword ```global``` to force Python to make use of the variable ```sum``` defined outside the function such that it modifies this variable (otherwise, a local variable would be created with the same name, but not returned. ---try it by commenting out line with ```global sum```).
Obviously, the keyword exists because there may be some legitimate use-case for it. Obviously, the keyword exists because there may be some legitimate use-case for it.
Generally, avoid such a pattern and have a clearly defined list of input and output values. Otherwise you loose all benefits to writing a function in the place. Generally, avoid such a pattern and have a clearly defined list of input and output values. Otherwise you loose all benefits to writing a function in the place.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Exercise ### Exercise
Rewrite the Fibonacci series as a function. The input value should be the number of Fibonacci numbers generated, the output should be a list containing the Fibonacci numbers. Rewrite the Fibonacci series as a function. The input value should be the number of Fibonacci numbers generated, the output should be a list containing the Fibonacci numbers.
Call your function and have it return 10 Fibonacci numbers. Call your function and have it return 10 Fibonacci numbers.
The output should be like: ```The Fibonacci numbers are: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]``` The output should be like: ```The Fibonacci numbers are: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# ... your code here .... # ... your code here ....
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Functions within functions ## Functions within functions
We can also define functions within functions, these are called *inner functions*. This can be helpful if we need to define a function that makes sense only within the context of the function we currently define. We can also define functions within functions, these are called *inner functions*. This can be helpful if we need to define a function that makes sense only within the context of the function we currently define.
The general syntax is: The general syntax is:
``` ```
def my_function(argument_1, argument_2,....): def my_function(argument_1, argument_2,....):
def inner_function_1(argument_X, argument_Y,...): def inner_function_1(argument_X, argument_Y,...):
# code for inner_function_1 # code for inner_function_1
def inner_function_2(argument_A, argument_B, ...): def inner_function_2(argument_A, argument_B, ...):
# code for inner_function_2 # code for inner_function_2
# code for outer function my_function # code for outer function my_function
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# Lambda functions # Lambda functions
Lambda functions are small anonymous functions. They can take any number of arguments but can have only one expression. Lambda functions are small anonymous functions. They can take any number of arguments but can have only one expression.
The term "anonymous" function means that lambda construct effectively defines a function (as we did above) --- but we do not assign a name it to but call it directly. The term "anonymous" function means that lambda construct effectively defines a function (as we did above) --- but we do not assign a name it to but call it directly.
The general syntax is: The general syntax is:
``` ```
lambda arguments : expression lambda arguments : expression
```` ````
In some cases, they can help to write code quite concise and are especially helpful if we use them inside other functions. In some cases, they can help to write code quite concise and are especially helpful if we use them inside other functions.
We could write our example calculating the sum as: We could write our example calculating the sum as:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
sum = lambda x, y : x + y sum = lambda x, y : x + y
print('The sum is: {}'.format(sum(3,4))) print('The sum is: {}'.format(sum(3,4)))
``` ```
%% Output %% Output
The sum is: 7 The sum is: 7
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Recursive Functions ## Recursive Functions
So far, the functions we have encountered were called once from the outside or from a loop. We can also call other functions from a function. Or, we can call the same function from within itself - we call this a ***recursive*** function. So far, the functions we have encountered were called once from the outside or from a loop. We can also call other functions from a function. Or, we can call the same function from within itself - we call this a ***recursive*** function.
The key thing about recursive functions is to define a suitable stopping point at which the function no longer calls itself. Otherwise, we would call the functions repeatedly in an endless loop. The key thing about recursive functions is to define a suitable stopping point at which the function no longer calls itself. Otherwise, we would call the functions repeatedly in an endless loop.
#### Demo #### Demo
Remember the definition of the Fibonacci numbers we have encountered earlier: \ Remember the definition of the Fibonacci numbers we have encountered earlier: \
The [Fibonacci Numbers](https://en.wikipedia.org/wiki/Fibonacci_number) are a sequence where the current number is derived from the sum of the two preceeding ones, i.e. $F_n = F_{n-1} + F_{n-2}$. The first two numbers are $F_1 = 0$ and $F_2 = 1$. The [Fibonacci Numbers](https://en.wikipedia.org/wiki/Fibonacci_number) are a sequence where the current number is derived from the sum of the two preceeding ones, i.e. $F_n = F_{n-1} + F_{n-2}$. The first two numbers are $F_1 = 0$ and $F_2 = 1$.
This already includes a recursive definition: $F_n = F_{n-1} + F_{n-2}$, apart from $F_1 = 0$ and $F_2 = 1$. This already includes a recursive definition: $F_n = F_{n-1} + F_{n-2}$, apart from $F_1 = 0$ and $F_2 = 1$.
Write a recursive functions to calculate the $F_n$ Fibonacci number and compute the first 10 numbers. Write a recursive functions to calculate the $F_n$ Fibonacci number and compute the first 10 numbers.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def Fibonacci(n): def Fibonacci(n):
if n < 0: # not defined for negative numbers if n < 0: # not defined for negative numbers
return None return None
if n <= 1: # first two numbers are 0, 1, stopping criterion if n <= 1: # first two numbers are 0, 1, stopping criterion
return n return n
else: # recursive call else: # recursive call
return Fibonacci(n-1) + Fibonacci(n-2) return Fibonacci(n-1) + Fibonacci(n-2)
for i in range(0,10): for i in range(0,10):
fib = Fibonacci(i) fib = Fibonacci(i)
print('the Fibonacci number is: {}'.format(fib)) print('the Fibonacci number is: {}'.format(fib))
``` ```
%% Output %% Output
the Fibonacci number is: 0 the Fibonacci number is: 0
the Fibonacci number is: 1 the Fibonacci number is: 1
the Fibonacci number is: 1 the Fibonacci number is: 1
the Fibonacci number is: 2 the Fibonacci number is: 2
the Fibonacci number is: 3 the Fibonacci number is: 3
the Fibonacci number is: 5 the Fibonacci number is: 5
the Fibonacci number is: 8 the Fibonacci number is: 8
the Fibonacci number is: 13 the Fibonacci number is: 13
the Fibonacci number is: 21 the Fibonacci number is: 21
the Fibonacci number is: 34 the Fibonacci number is: 34
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
#### Demo #### Demo
We can rewrite this recursive function as a one-line Lambda function. We can rewrite this recursive function as a one-line Lambda function.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
Fibonacci = lambda n: n if n <= 1 else Fibonacci(n-1) + Fibonacci(n-2) Fibonacci = lambda n: n if n <= 1 else Fibonacci(n-1) + Fibonacci(n-2)
for i in range(0,10): for i in range(-3,10):
fib = Fibonacci(i) fib = Fibonacci(i)
print('the Fibonacci number is: {}'.format(fib)) print('the Fibonacci number is: {}'.format(fib))
``` ```
%% Output %% Output
the Fibonacci number is: -3
the Fibonacci number is: -2
the Fibonacci number is: -1
the Fibonacci number is: 0 the Fibonacci number is: 0
the Fibonacci number is: 1 the Fibonacci number is: 1
the Fibonacci number is: 1 the Fibonacci number is: 1
the Fibonacci number is: 2 the Fibonacci number is: 2
the Fibonacci number is: 3 the Fibonacci number is: 3
the Fibonacci number is: 5 the Fibonacci number is: 5
the Fibonacci number is: 8 the Fibonacci number is: 8
the Fibonacci number is: 13 the Fibonacci number is: 13
the Fibonacci number is: 21 the Fibonacci number is: 21
the Fibonacci number is: 34 the Fibonacci number is: 34
......
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
--- ---
### Exercise ### Exercise
Imagine we are a bank and need to establish a way for us to track the transactions with customers. Imagine we are a bank and need to establish a way for us to track the transactions with customers.
In a very simple scenario, we need an account for each customer, that has the following properties: In a very simple scenario, we need an account for each customer, that has the following properties:
* It is associated with a customer with their name. * It is associated with a customer with their name.
* For simplicity, we only consider euros (i.e. no cents, just integer values). * For simplicity, we only consider euros (i.e. no cents, just integer values).
* Customers can put money into the account, withdraw money and ask for the balance. * Customers can put money into the account, withdraw money and ask for the balance.
* The bank does not offer credit or overdraft. * The bank does not offer credit or overdraft.
Implement this as a class. Implement this as a class.
First, think about why the above requirements are ambiguous and not sufficient (and then come up with a way to mitigate this.) First, think about why the above requirements are ambiguous and not sufficient (and then come up with a way to mitigate this.)
Then, think about which cases you need to consider in your implementation. Then, think about which cases you need to consider in your implementation.
We need to consider: We need to consider:
* "name" is not detailed enough: Do we mean the full name, just the surname or the given name, any middle names? Also, depending on the culture, the concept of a name may be different from what we expect in our western world. * "name" is not detailed enough: Do we mean the full name, just the surname or the given name, any middle names? Also, depending on the culture, the concept of a name may be different from what we expect in our western world.
For simplicity we just go with the surname as a single identifier. Obviously, this will create problems down the line, as many people share the same surname. For simplicity we just go with the surname as a single identifier. Obviously, this will create problems down the line, as many people share the same surname.
* We do not have any specification for gender assignments. Ignore for now. * We do not have any specification for gender assignments. Ignore for now.
* When a withdrawal is made, we need to check that: * When a withdrawal is made, we need to check that:
* There are sufficient funds in the account * There are sufficient funds in the account
* The withdrawal is a positive integer number * The withdrawal is a positive integer number
* We can only withdraw the full value of the balance at most, since there is no overdraft/credit * We can only withdraw the full value of the balance at most, since there is no overdraft/credit
* When depositing money, we need to check that: * When depositing money, we need to check that:
* The deposit is a positive integer number. * The deposit is a positive integer number.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
class Account(): class Account():
def __init__(self, name, balance = 0): def __init__(self, name, balance = 0):
self._name = name self._name = name
# what can we improve in the following line?
self._balance = int(balance) self._balance = int(balance)
if self._balance < 0: if self._balance < 0:
self._balance = 0 self._balance = 0
def balance(self): def balance(self):
return self._balance return self._balance
def name(self): def name(self):
return self._name return self._name
def deposit(self, amount): def deposit(self, amount):
if type(amount) == int and amount > 0: if type(amount) == int and amount > 0:
self._balance = self._balance + amount self._balance = self._balance + amount
else: else:
print('Invalid deposit') print('Invalid deposit')
def withdrawal(self, amount): def withdrawal(self, amount):
if type(amount) == int and amount > 0 and amount < self._balance: if type(amount) == int and amount > 0 and amount < self._balance:
self._balance = self._balance - amount self._balance = self._balance - amount
return self._balance return self._balance
else: else:
print('Invalid withdrawal') print('Invalid withdrawal')
return None return None
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
account = Account('Smith') account = Account('Smith')
print('Opened account for {}'.format(account.name())) print('Opened account for {}'.format(account.name()))
print('Current balance: {}'.format(account.balance())) print('Current balance: {}'.format(account.balance()))
# make a deposit # make a deposit
account.deposit(10) account.deposit(10)
print('Current balance: {}'.format(account.balance())) print('Current balance: {}'.format(account.balance()))
# try to make an invalid deposit -- should produce an error message # try to make an invalid deposit -- should produce an error message
account.deposit(-10) account.deposit(-10)
# try to make an invalid deposit -- should produce an error message # try to make an invalid deposit -- should produce an error message
account.deposit(10.5) account.deposit(10.5)
# try to make an invalid deposit -- should produce an error message # try to make an invalid deposit -- should produce an error message
account.deposit('ten') account.deposit('ten')
# withdraw some money # withdraw some money
my_money = account.withdrawal(5) my_money = account.withdrawal(5)
print('I have now {} euros in my hand'.format(my_money)) print('I have now {} euros in my hand'.format(my_money))
print('Current balance: {}'.format(account.balance())) print('Current balance: {}'.format(account.balance()))
# try to make an invalid withdrawal -- should produce an error message and we have "nothing" in our hand # try to make an invalid withdrawal -- should produce an error message and we have "nothing" in our hand
my_money = account.withdrawal(-10) my_money = account.withdrawal(-10)
print('I have now {} euros in my hand'.format(my_money)) print('I have now {} euros in my hand'.format(my_money))
# try to make an invalid withdrawal -- should produce an error message and we have "nothing" in our hand # try to make an invalid withdrawal -- should produce an error message and we have "nothing" in our hand
my_money = account.withdrawal(10.5) my_money = account.withdrawal(10.5)
print('I have now {} euros in my hand'.format(my_money)) print('I have now {} euros in my hand'.format(my_money))
# try to make an invalid withdrawal -- should produce an error message and we have "nothing" in our hand # try to make an invalid withdrawal -- should produce an error message and we have "nothing" in our hand
my_money = account.withdrawal('ten') my_money = account.withdrawal('ten')
print('I have now {} euros in my hand'.format(my_money)) print('I have now {} euros in my hand'.format(my_money))
# try to make an invalid withdrawal -- should produce an error message and we have "nothing" in our hand # try to make an invalid withdrawal -- should produce an error message and we have "nothing" in our hand
my_money = account.withdrawal(500) my_money = account.withdrawal(500)
print('I have now {} euros in my hand'.format(my_money)) print('I have now {} euros in my hand'.format(my_money))
``` ```
%% Output %% Output
Opened account for Smith Opened account for Smith
Current balance: 0 Current balance: 0
Current balance: 10 Current balance: 10
Invalid deposit Invalid deposit
Invalid deposit Invalid deposit
Invalid deposit Invalid deposit
I have now 5 euros in my hand I have now 5 euros in my hand
Current balance: 5 Current balance: 5
Invalid withdrawal Invalid withdrawal
I have now None euros in my hand I have now None euros in my hand
Invalid withdrawal Invalid withdrawal
I have now None euros in my hand I have now None euros in my hand
Invalid withdrawal Invalid withdrawal
I have now None euros in my hand I have now None euros in my hand
Invalid withdrawal Invalid withdrawal
I have now None euros in my hand I have now None euros in my hand
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment