Commit 741ac33c authored by Franck Thollard's avatar Franck Thollard
Browse files

WIP, refactoring function and testing

parent 0aab5d43
Pipeline #32191 passed with stage
in 58 seconds
......@@ -277,856 +277,15 @@
}
},
"source": [
"## All Python functions return exactly one object but... `None` and `tuple`"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
},
{
"data": {
"text/plain": [
"NoneType"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"type(print())"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(1, 'hello', 3)\n"
]
}
],
"source": [
"def return_a_tuple():\n",
" return 1, 'hello', 3 # a tuple, same as (1, 'hello', 3)\n",
"\n",
"my_tuple = return_a_tuple()\n",
"print(my_tuple)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"hello\n"
]
}
],
"source": [
"a, b, c = return_a_tuple()\n",
"print(b)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Function call: namespaces and objects \"passed by references\"\n",
"\n",
"For each function call:\n",
"\n",
"- a **new namespace** is created (as at the beginning of a module) \n",
"- 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",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"## Function call: objects \"passed by references\"\n",
"\n",
"Exercice: use 2 schemes \"namespaces-objects\" to understand these 2 pieces of code. "
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[4] 2\n"
]
}
],
"source": [
"number = 2\n",
"mylist = []\n",
"\n",
"def my_strange_append_square(l, n):\n",
" # new function namespace with names \"l\" and \"n\"\n",
" n = n**2\n",
" l.append(n)\n",
"\n",
"my_strange_append_square(mylist, number)\n",
"print(mylist, number)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[4] 2\n"
]
}
],
"source": [
"number = 2\n",
"mylist = []\n",
"\n",
"def my_strange_append_square(mylist, number):\n",
" # new function namespace with names \"mylist\" and \"number\"\n",
" number = number**2\n",
" mylist.append( number)\n",
" \n",
"my_strange_append_square(mylist, number)\n",
"print(mylist, number)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"## Global vs Local variables\n",
"\n",
"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.\n",
"\n",
"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",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Inside the function local result:\t 20\n",
"Outside the function global result:\t 0\n"
]
}
],
"source": [
"# global variables\n",
"result = 0\n",
"multiplicator = 2\n",
"\n",
"def multiply(arg0):\n",
" # here we create a new name `result` in the function namespace\n",
" # `result` is a local variable\n",
" # we can use the global variable `multiplicator`\n",
" result = multiplicator * arg0\n",
" print('Inside the function local result:\\t', result)\n",
" return result\n",
"\n",
"multiply(10)\n",
"print('Outside the function global result:\\t', result)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- Global variables can be used in a function.\n",
"- Global variables can not be modified in a function (except with the `global` keyword. Discourage!)."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"## Global vs Local variables: `global` keyword\n",
"\n",
"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",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"global variable locally defined\n",
"global variable locally defined\n"
]
}
],
"source": [
"def func():\n",
" global me\n",
" # Defined locally but declared as global\n",
" me = 'global variable locally defined'\n",
" print(me)\n",
"\n",
"func()\n",
"# Ask for a global variable\n",
"print(me)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1, 2, 3, 4, "
]
}
],
"source": [
"delta = 0\n",
"\n",
"def add_1_to_delta():\n",
" global delta\n",
" # global variable modified in a function\n",
" delta += 1\n",
"\n",
"for i in range(4):\n",
" add_1_to_delta()\n",
" print(delta, end=', ')"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Function Arguments\n",
"\n",
"You can call a function by using the following types of formal arguments:\n",
"\n",
" - Required arguments\n",
" - Keyword arguments\n",
" - Default arguments\n",
" - Variable-length arguments"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Required arguments\n",
"\n",
"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",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"arg0 + 2*arg1 = 4 + 2*6 = 16\n"
]
},
{
"data": {
"text/plain": [
"16"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def myfunc(arg0, arg1):\n",
" \"Return the sum of the first argument with twice the second one.\"\n",
" result = arg0 + 2*arg1\n",
" print(f'arg0 + 2*arg1 = {arg0} + 2*{arg1} = {result}')\n",
" return result\n",
"\n",
"myfunc(4, 6)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"source": [
"To call the function `myfunc`, you definitely need to pass two arguments, otherwise it gives a syntax error."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Keyword arguments\n",
"\n",
"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",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"arg0 + 2*arg1 = 2 + 2*3 = 8\n"
]
},
{
"data": {
"text/plain": [
"8"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"myfunc(arg1=3, arg0=2)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Default arguments\n",
"\n",
"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",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"arg0 + 2*arg1 = a + 2*n = ann\n"
]
}
],
"source": [
"def myfunc1(arg0, arg1=None):\n",
" \"Return the sum of the first argument with twice the second one.\"\n",
" if arg1 is None:\n",
" if type(arg0) == int:\n",
" arg1 = 0\n",
" else:\n",
" arg1 = \"\"\n",
" myfunc(arg0, arg1)\n",
"\n",
"myfunc1(\"a\", \"n\")"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"arg0 + 2*arg1 = 1 + 2*3 = 7\n"
]
}
],
"source": [
"myfunc1(1, 3)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Default arguments\n",
"\n",
"**Warning:** the default arguments are created only once, at the function definition! They are stored in a tuple associated with the function object."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"def do_not_use_mutable_object_for_default_arg(l=[]):\n",
" l.append(1)\n",
" print(l)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Exercice:** what will be the result of 3 calls of this function? Use a namespaces-objects diagram!"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Default arguments\n",
"\n",
"**Warning:** the default arguments are created only once, at the function definition! They are stored in a tuple associated with the function object."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def do_not_use_mutable_object_for_default_arg(l=[]):\n",
" l.append(1)\n",
" print(l)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1]\n",
"[1, 1]\n",
"[1, 1, 1]\n"
]
}
],
"source": [
"do_not_use_mutable_object_for_default_arg()\n",
"do_not_use_mutable_object_for_default_arg()\n",
"do_not_use_mutable_object_for_default_arg()"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1]\n",
"[1]\n",
"[1]\n",
"[1, 2, 3, 1]\n"
]
},
{
"data": {
"text/plain": [
"[1, 2, 3, 1]"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def how_to_use_list_as_default_arg(l=None):\n",
" if l is None:\n",
" l = []\n",
" l.append(1)\n",
" print(l)\n",
"\n",
"how_to_use_list_as_default_arg()\n",
"how_to_use_list_as_default_arg()\n",
"how_to_use_list_as_default_arg()\n",
"l1 = [1,2,3]\n",
"how_to_use_list_as_default_arg(l1)\n",
"l1"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Variable-length arguments\n",
"\n",
"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.\n",
"\n",
"An asterisk (*) is placed before the variable name that holds the values of all nonkeyword variable arguments."
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"args = ()\n",
"totalsum = 0\n",
"args = (4,)\n",
"totalsum = 4\n",
"args = (4, 3, 4, 7)\n",
"totalsum = 18\n"
]
},
{
"data": {
"text/plain": [
"18"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def sum_args(*args):\n",
" \"\"\"Return the sum of numbers.\"\"\"\n",
" totalsum = 0\n",
" print('args =', args)\n",
" for var in args:\n",
" totalsum += var\n",
" print('totalsum =', totalsum)\n",
" return totalsum\n",
"\n",
"sum_args()\n",
"sum_args(4)\n",
"sum_args(4, 3, 4, 7)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"### Variable-length arguments\n",
"\n",
"There is also a (very useful) syntax with two asterisks `**`, which works like this:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"call:\n",
"\ta = 1\n",
"\targs = (3,)\n",
"\tkwargs = {'toto': 3, 'titi': 3}\n",
"call:\n",
"\ta = a\n",
"\targs = ()\n",
"\tkwargs = {'bob': 3}\n"
]
}