{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Post Exam Python-Functions\n", "\n", "### Looking at what a module contains, and its documentation\n", "\n", "Once a module is imported, we can list the symbols it provides using the `dir` function:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']\n" ] } ], "source": [ "import math\n", "\n", "print(dir(math))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "And using the function `help` we can get a description of each function (almost .. not all functions have docstrings, as they are technically called, but the vast majority of functions are documented this way). " ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on built-in function log in module math:\n", "\n", "log(...)\n", " log(x, [base=math.e])\n", " Return the logarithm of x to the given base.\n", " \n", " If the base not specified, returns the natural logarithm (base e) of x.\n", "\n" ] } ], "source": [ "help(math.log)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "We can also use the `help` function directly on modules: Try\n", "\n", " help(math) \n", "\n", "Some very useful modules form the Python standard library are `os`, `sys`, `math`. \n", "\n", "A complete lists of standard modules for Python 2 and Python 3 are available at http://docs.python.org/2/library/ and http://docs.python.org/3/library/, respectively." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Variable Names\n", "Variable names in Python can contain alphanumerical characters `a-z`, `A-Z`, `0-9` and some special characters such as `_`. Normal variable names must start with a letter. \n", "\n", "By convention, variable names start with a lower-case letter, and Class names start with a capital letter. \n", "\n", "In addition, there are a number of Python keywords that cannot be used as variable names. These keywords are:\n", "\n", " and, as, assert, break, class, continue, def, del, elif, else, except, \n", " exec, finally, for, from, global, if, import, in, is, lambda, not, or,\n", " pass, print, raise, return, try, while, with, yield\n", "\n", "Note: Be aware of the keyword `lambda`, which could easily be a natural variable name in a scientific program. But being a keyword, it cannot be used as a variable name." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Functions\n", "\n", "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.\n", "\n", "As you already know, Python gives you many built-in functions like *print()*, etc. but you can also create your own functions. These functions are called __user-defined functions__." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Defining a Function\n", "\n", "You can define functions to provide the desired functionality. \n", "\n", "* Function blocks begin with the keyword `def` followed by the `function name` and parentheses `()` followed by a colon `:`.\n", "* Use the function naming rules: lowercase with words separated by underscores as necessary to improve readability. (this convention is not always followed and does not prevent operation, but it is good to develop a style and stick to it.\n", "* Any input parameters or arguments should be placed within the parentheses. You can also define parameters inside these parentheses.\n", "* The code block within every function starts is after the colon `:` and is indented.\n", "* The first statement of a function can be an optional statement (although you will not gain full marks in this course if not included) - the documentation string of the function or docstring.\n", "* The docstring is bounded by `\"\"\"....\"\"\"` \n", "* The statement `return [expression]` exits a function, optionally passing back an expression to the caller. A `return` statement with no arguments is the same as `return None`." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### User defined **functions**: Example\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def func0(): \n", " print(\"test\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Calling a Function\n", "Defining a *function* only gives it a *name*, specifies the parameters that are to be included in the function and structures the blocks of code.\n", "\n", "Once the basic structure of a function is finalized, you can execute it by calling it from another function or directly from the *Python* prompt." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "test\n" ] } ], "source": [ "func0()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### User defined **functions**: Example2" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def func1(s):\n", " \"\"\"\n", " Print a string 's' and tell how many characters it has \n", " \"\"\"\n", " \n", " print(s + \" has \" + str(len(s)) + \" characters\")" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "test has 4 characters\n" ] } ], "source": [ "func1(\"test\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## `Help(functionname)` or `functionname?`\n", "Using the function `help` will return a description of each function (almost .. not all functions have docstrings, as they are technically called, but the vast majority of functions are documented this way). " ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on function func1 in module __main__:\n", "\n", "func1(s)\n", " Print a string 's' and tell how many characters it has\n", "\n" ] } ], "source": [ "help(func1)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### User defined functions: `return`\n", "\n", "Functions that returns a value use the `return` keyword:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def square(x):\n", " \"\"\"\n", " Return the square of x.\n", " \"\"\"\n", " return x ** 2" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "16" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "square(4)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### User defined **functions**: Example 3\n", "\n", "We can return multiple values from a function using tuples:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def powers(x):\n", " \"\"\"\n", " Return a few powers of x.\n", " \"\"\"\n", " return x ** 2, x ** 3, x ** 4" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "(9, 27, 81)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "powers(3)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "27\n" ] } ], "source": [ "x2, x3, x4 = powers(3)\n", "\n", "print(x3)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Scope of a variable\n", "A *local* variable is defined inside the Python function. *Local* variables are only accessible within their local scope. A *global* variable is defined outside the Python function. *Global* variables are accessible throughout the program.\n", "\n", "\n", "### Pass by reference vs value\n", "All parameters (arguments) in the *Python* language are passed by reference. It means if you change what a parameter refers to within a function, the change also reflects back in the calling function. For example:\n", "### User defined example 4" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Values inside the function: [10, 20, 30, [1, 2, 3, 4]]\n", "Values outside the function: [10, 20, 30, [1, 2, 3, 4]]\n" ] } ], "source": [ "# Function definition is here\n", "def changeme( mylist ):\n", " \"This changes a passed list into this function\"\n", " mylist.append([1,2,3,4]);\n", " print( \"Values inside the function: \", mylist)\n", " return\n", "\n", "# Now you can call changeme function\n", "mylist = [10,20,30];\n", "changeme( mylist );\n", "print( \"Values outside the function: \", mylist)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Here, we are maintaining reference of the passed object and appending values in the same object. Hence thr result obtained. However if instead we assign (using the assignment operator \"=\" a new reference to the passed object *mylist* it becomes a new *local* variable onside the function and the *mylist* outside the funcion is unchanged." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Values inside the function: [1, 2, 3, 4]\n", "Values outside the function: [10, 20, 30]\n" ] } ], "source": [ "# Function definition is here\n", "def changeme( mylist ):\n", " \"This changes a passed list into this function\"\n", " mylist = [1,2,3,4]; # This would assig new reference in mylist\n", " print( \"Values inside the function: \", mylist)\n", " return\n", "\n", "# Now you can call changeme function\n", "mylist = [10,20,30];\n", "changeme( mylist );\n", "print (\"Values outside the function: \", mylist)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## User defined example 5\n", "### Default argument and keyword arguments\n", "\n", "In a definition of a function, we can give default values to the arguments the function takes:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "def myfunc(x, p=2, debug=False):\n", " if debug:\n", " print(\"evaluating myfunc for x = \" + str(x) + \" using exponent p = \" + str(p))\n", " return x**p" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "If we don't provide a value of the `debug` argument when calling the the function `myfunc` it defaults to the value provided in the function definition:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "25" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "myfunc(5)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "evaluating myfunc for x = 5 using exponent p = 2\n" ] }, { "data": { "text/plain": [ "25" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "myfunc(5, debug=True)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "If we explicitly list the name of the arguments in the function calls, they do not need to come in the same order as in the function definition. This is called *keyword* arguments, and is often very useful in functions that takes a lot of optional arguments." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "evaluating myfunc for x = 7 using exponent p = 3\n" ] }, { "data": { "text/plain": [ "343" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "myfunc(p=3, debug=True, x=7)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Unnamed functions (lambda function)\n", "\n", "In Python we can also create unnamed functions, using the `lambda` keyword:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "f1 = lambda x: x**2\n", " \n", "# is equivalent to \n", "\n", "def f2(x):\n", " return x**2" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "(4, 4)" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f1(2), f2(2)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Unamed functions (lambda)\n", "\n", "This technique is useful for example when we want to pass a simple function as an argument to another function, like this:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# map is a built-in python function\n", "map(lambda x: x**2, range(-3,4))" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "[9, 4, 1, 0, 1, 4, 9]" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# in python 3 we can use `list(...)` to convert the iterator to an explicit list\n", "list(map(lambda x: x**2, range(-3,4)))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exceptions" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "In Python errors are managed with a special language construct called \"Exceptions\". When errors occur exceptions can be raised, which interrupts the normal program flow and fallback to somewhere else in the code where the closest try-except statement is defined." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "To generate an exception we can use the `raise` statement, which takes an argument that must be an instance of the class `BaseException` or a class derived from it. " ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "ename": "Exception", "evalue": "description of the error", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mException\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"description of the error\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mException\u001b[0m: description of the error" ] } ], "source": [ "raise Exception(\"description of the error\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Exceptions\n", "A typical use of exceptions is to abort functions when some error condition occurs, for example:\n", "\n", " def my_function(arguments):\n", " \n", " if not verify(arguments):\n", " raise Exception(\"Invalid arguments\")\n", " \n", " # rest of the code goes here" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "To gracefully catch errors that are generated by functions and class methods, or by the Python interpreter itself, use the `try` and `except` statements:\n", "\n", " try:\n", " # normal code goes here\n", " except:\n", " # code for error handling goes here\n", " # this code is not executed unless the code\n", " # above generated an error\n", "\n", "For example:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "test\n", "Caught an exception\n" ] } ], "source": [ "try:\n", " print(\"test\")\n", " # generate an error: the variable test is not defined\n", " print(test)\n", "except:\n", " print(\"Caught an exception\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "To get information about the error, we can access the `Exception` class instance that describes the exception by using for example:\n", "\n", " except Exception as e:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "test\n", "Caught an exception:name 'test' is not defined\n" ] } ], "source": [ "try:\n", " print(\"test\")\n", " # generate an error: the variable test is not defined\n", " print(test)\n", "except Exception as e:\n", " print(\"Caught an exception:\" + str(e))" ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3", "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", "version": "3.7.0" } }, "nbformat": 4, "nbformat_minor": 1 }