Newer
Older
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Agenda\n",
"\n",
"* Adding structure to Python code\n",
"* Functions\n",
"* Namespaces\n",
"* Modules"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Code Structure"
]
},
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Adding structure to Python code\n",
"\n",
"* There are many good reasons why we want to organize our code and add structure to it\n",
" * Reuse : We don't want to do things twice\n",
" * Readability : structured code can be read like a language\n",
" * Maintainability : If we don't have a good structure in code, we can spend a lot time with searching\n",
"* In Python we have different concepts to give structure to our code:\n",
" * Functions\n",
" * Namespaces\n",
" * Modules\n",
" * Classes (we will come back to this great concept at the end of this course)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Functions"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Usage of Functions\n",
"\n",
"* Functions allow us to define a block of code that can be called from anywhere\n",
"* Functions accept *parameters* (arguments) as input into the code block\n",
"* Optionally, functions can *return* a value\n",
"* As soon as you repeat the same or similar sequence of code, consider writing a function\n",
"* Functions are called with the function name, followed by ()\n",
" * If the function accepts parameters, they are listed inside (), separated with comma\n",
" * If the function returns a value, it can be assigned to a variable\n",
"\n",
" \n",
"Here is an example:"
]
},
{
"cell_type": "code",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"4\n"
]
}
],
"source": [
"my_number = max(3, 4, 2) # calling the function with 3 arguments and assigning the result to a variable\n",
"print(my_number) # also print is a function"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Definition of Functions\n",
"\n",
"* To define a function, we use the `def`keyord, followed by the function name\n",
"* After the function name we declare in () which parameters are allowed\n",
"* If we want to return a value, we can do this anywhere with the `return` statement, followed by the return value(s)"
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"4\n"
]
}
],
"source": [
"# Define a function that takes two arguments and returns the bigger one\n",
"def bigger_of_two(a, b):\n",
" if a > b:\n",
" return a\n",
" else:\n",
" return b\n",
"\n",
"# Call the function with two arguments and print the result\n",
"print(bigger_of_two(4, 3))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"* Variables that are first used in a function are only known inside this function\n",
"* However functions can access variables of the outer scope (e.g. global variables)\n",
"* Variables in the most outer scope are called \"global variables\"\n",
"* Variables in a closed inner scope are called \"local variables\""
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Value from outer scope: 8\n",
"Value from same scope: 3\n"
]
},
{
"ename": "NameError",
"evalue": "name 'y' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[3], line 8\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mValue from same scope:\u001b[39m\u001b[38;5;124m\"\u001b[39m, y) \u001b[38;5;66;03m# y is not accessible from the outer scope\u001b[39;00m\n\u001b[1;32m 7\u001b[0m some_function()\n\u001b[0;32m----> 8\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mValue from inner scope:\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[43my\u001b[49m)\n",
"\u001b[0;31mNameError\u001b[0m: name 'y' is not defined"
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
"source": [
"x = 8\n",
"def some_function():\n",
" print(\"Value from outer scope:\", x) # x is accessible from the inner scope\n",
" y = 3\n",
" print(\"Value from same scope:\", y) # y is not accessible from the outer scope\n",
"\n",
"some_function()ß\n",
"print(\"Value from inner scope:\", y)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Assigning multiple values\n",
"\n",
"* in Python we can assign multiple values to multiple variables in one line\n",
"* Accordingly, we can write functions that return multiple values, which can be very handy"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
"source": [
"def get_min_max(list):\n",
" minimum = min(list)\n",
" maximum = max(list)\n",
" return minimum, maximum # returning multiple values\n",
"\n",
"list_min, list_max = get_min_max([1, 2, 3, 4, 5]) # multiple assignment (first value goes to a, second to b)\n",
"\n",
"print(list_min)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## More About Funtions in Python\n",
"\n",
"* Default Parameter Value : You can define default values, in case the function is called without parameter"
]
},
{
"cell_type": "code",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
"source": [
"def default_argument(a, b, c=3): # default value for c\n",
" return a + b + c\n",
"print(default_argument(1, 2)) # c will be 3"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* Arbitrary Arguments, *args : If you do not know how many arguments that will be passed into your function, add a * before the argument name"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"def arbitrary_argument(*args): # variable number of arguments\n",
" sum = 0\n",
" for a in args:\n",
" sum += a\n",
" return sum\n",
"\n",
"print(arbitrary_argument(1, 2, 4, 6))"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* There is more we can do with functions, but this is a good start."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Using Modules I\n",
"\n",
"* One of the biggest advantages of Python is the incredible number of modules that are available\n",
"* Modules are pieces of code that exist somewhere else (typically in another file)\n",
"* Modules can be imported with the `` import module_name `` statement\n",
"* The module name can be any installed python module, \n",
"* or the name of file somewhere in your project (name without the '.py' ending)\n",
"* Functions of a module are accessible with the module name and the `` . `` operator"
"cell_type": "code",
"execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"import math # importing a module\n",
"\n",
"math.sqrt(16) # using a function from the module"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"* If a module can be organized in submodules by placing them in a folder or subfolder of your project\n",
"* The module name will then be `` module.submodule `` (according to the fodler structure)\n",
"* To access a function you will have to write something like `` module.submodule.function() ``\n",
"* In this case we want to create a shortcut.\n",
"* In Python this can be done with as `` as `` order: ``import folder.module as mod ``"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
"source": [
"import pandas.plotting as pdp # importing a submodule\n",
"\n",
"pdp.lag_plot() # using a function from the submodule"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Installing Modules\n",
"\n",
"* As mentioned earlier, Python has a vast variety of modules (currently about 570k registered packages)\n",
"* You can find the official registry here: https://pypi.org/\n",
"* Luckily we don't have to search and copy them from the internet\n",
"* Python has package management tool, called pip that helps us to install modules\n",
"\n",
"```\n",
"pip install <module name>\n",
"pip install pandas \n",
"```\n",
"\n",
"if you have several Python versions you may have to use the specifice pip command\n",
"\n",
"```\n",
"pip3 install <module name>\n",
"```\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Crating a Module\n",
"\n",
"* At some point your code will get bigger\n",
"* And also you might want to reuse your own code in other projects\n",
"* In this case it is a good idea to start organizing your code in modules\n",
"* Creating a modules is as easy as creating a new .py file \n",
"* Let's code a simple example."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Namespaces"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Namespace Rules\n",
"\n",
"<img style=\"float: right; padding-right: 50pt;\" src=\"https://files.realpython.com/media/t.fd7bd78bbb47.png\" width=\"300pt\">\n",
"\n",
"* Now that we know functions and modules, it's time to have a closer look at namespaces\n",
"* A namespaces the scope in which a name (variable, function, class, ...) is valid\n",
"* Names must be unique in their namespaces\n",
"* Python knows3 types of namespaces with the following rules:\n",
" 1. Local: If you refer to x inside a function, then the interpreter first searches for it in the innermost scope that’s local to that function.\n",
" 2. Enclosing: If x isn’t in the local scope but appears in a function that resides inside another function, then the interpreter searches in the enclosing function’s scope.\n",
" 3. Global: If neither of the above searches is fruitful, then the interpreter looks in the global scope next.\n",
" 4. Built-in: If it can’t find x anywhere else, then the interpreter tries the built-in scope."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Working with Namespaces\n",
"\n",
"* In Python functions, modules (and classes) act as enclosing and local namespaces\n",
"* You might have realized: modules automatically act as a namespace\n",
"* Their structure determine the scope of names\n",
"* Considering memory: \n",
" * Global variables remain in the RAM all time\n",
" * Local variables only use memory while the object defining the namespace exists"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"9\n",
"1\n",
"2\n",
"3\n"
]
}
],
"source": [
"x = 1\n",
"def namespaces():\n",
" def subspaces():\n",
" z = 3\n",
" print(pow(3,2)) # access namespaces from the built-in scope\n",
" print(x) # access x from the global scope\n",
" print(y) # access y from the enclosing scope\n",
" print(z) # access z from the local scope\n",
"\n",
" y = 2\n",
" subspaces()\n",
" print(y) # access y from the local scope\n",
" print(z) # z is not accessible from the outer scope (NameError)\n",
"\n",
"namespaces()"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## For the Geeks\n",
"\n",
"* Careful about redeclaration!\n",
"* While an enclosing variable x can be read in an inner namespaces, a new variable will be created at the moment you assign a value to this variable."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2\n",
"1\n"
]
}
],
"source": [
"def namespaces():\n",
" def subspaces():\n",
" x = 2 # x is now a local variable\n",
" print(x)\n",
"\n",
" x = 1 # x is a local variable of namespaces\n",
" subspaces()\n",
" print(x)\n",
"\n",
"namespaces()"
]
}
],
"metadata": {
"celltoolbar": "Slideshow",
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",