{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Lesson A8 – Functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Throughout the previous parts of this course we encountered many functions already. We know that a function\n", "is an object that can be called, that arguments can be passed to it and that functions return other objects." ] }, { "cell_type": "markdown", "metadata": { "run_control": { "marked": true } }, "source": [ "```python\n", "returned_object = fxn(argurments)\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You might have noticed, that we sometimes pass arguments directly. We call these arguments *positional arguments*." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "positional argument\n" ] } ], "source": [ "print(\"positional argument\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Positional arguments are often required arguments. The order of positional arguments passed matters." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "range expected 1 arguments, got 0", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# Needs a positional argument\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: range expected 1 arguments, got 0" ] } ], "source": [ "range() # Needs a positional argument" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "range(0, 10)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "range(10) # One argument is interpreted as stop" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "range(1, 10)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "range(1, 10) # Two arguments are interpreted as start, stop" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "On the other hand we used some other arguments explicitly with a name. We call these arguments *keyword arguments*.\n", "These arguments are optional and their order does not matter, since they are passed with a name. Keyword arguments always need to come after all positional arguments." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "positional and keyword arguments!" ] } ], "source": [ "print(\"positional and keyword arguments\", end=\"!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "**Note:** We distinguish function arguments as __positional__ arguments (required and interpreted by order) and __keyword__ arguments (optional and identified by name).\n", " \n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will now see how to write our own functions and how to control their behaviour by specifying their arguments. The purpose of functions is to bundle blocks of code in reusable objects under a label for identification. After loops, functions are our main tool to execute code many, many times that we have only written once." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Function definitions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Besides using functions provided by Python modules, we can write our own functions. The `def` directive defines a code block as a function." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "def our_first_function():\n", " \"\"\"This is our first function\"\"\"\n", " \n", " print(\"Hey,\")\n", " print(\"this is our first function!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Our function does not expect any arguments: the parenthesis in the above definition are empty. Calling it, executes the function body. Obviously a function needs\n", "to be defined first, before we can call it." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hey,\n", "this is our first function!\n" ] } ], "source": [ "our_first_function()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The call of `our_first_function` printed a message to the screen. It did, however, not return a result. Precisely, if we try to store the return value of the function into a variable, we obtain `None`." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hey,\n", "this is our first function!\n", "None\n" ] } ], "source": [ "returned = our_first_function()\n", "print(returned)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The print output to the screen is a side-effect of our function.\n", "Often we want functions to return something to the main program (e.g. the result of a calculation). \n", "We implement this with a `return` statement in the function definition." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "def return_one():\n", " \"\"\"Always describe your function here\n", " \n", " Returns:\n", " 1\n", " \"\"\"\n", " \n", " return 1" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] } ], "source": [ "returned = return_one()\n", "print(returned)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "**Advanced:** A function that does not return anything explicitly, returns `None` by default. Leaving out the `return` statement within a function definition is equivalent to a bare `return` or an explicit `return None`.\n", "\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "```python\n", "def no_return():\n", " pass # do nothing\n", "\n", "def bare_return():\n", " return\n", "\n", "def explicit_return():\n", " return None\n", "\n", "```\n", "\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once a return is encountered during the execution of the function, we exit the function. Only the first return statement met will have an effect. Everything after a return statement is not executed." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def return_this_or_that():\n", " if True:\n", " return True\n", " return False\n", "\n", "return_this_or_that()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we want to make our function handle arguments, we need to define what it expects in the first\n", "line of our definition. We put the argument within the parenthesis, we have left empty so far." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "def repeat_print(s, i=2):\n", " \"\"\"Repeated calls of `print()`\n", " \n", " Args:\n", " s (str): String object to print\n", " i (int): How often to print\n", " \n", " Returns:\n", " None\n", " \"\"\"\n", " \n", " for _ in range(i):\n", " print(s)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello!\n", "Hello!\n" ] } ], "source": [ "# Call of repeat_print\n", "repeat_print(\"Hello!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We use a required positional argument `s` here and an optional keyword argument `i`. When we call this function we need to pass at least one argument to it. The string `\"Hello!\"` we passed is interpreted by position as a value for `s`. Within the function, `s` is now defined as `s = \"Hello!\"`. By default, if we do not pass anything else, `i` is set to `i = 2` (two repeated prints). Optionally we can also set the parameter `i` to a different integer. In this case we need to pass it by name (`i=3`) after the positional argument." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hi!\n", "Hi!\n", "Hi!\n" ] } ], "source": [ "# Call of repeat_print\n", "repeat_print(\"Hi!\", i=3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note, that it is always a good idea to document what your function does with a comment directly at the top of the function body. These comments, called *docstrings* are also used when you call `help()` on your function." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on function repeat_print in module __main__:\n", "\n", "repeat_print(s, i=2)\n", " Repeated calls of `print()`\n", " \n", " Args:\n", " s (str): String object to print\n", " i (int): How often to print\n", " \n", " Returns:\n", " None\n", "\n" ] } ], "source": [ "help(repeat_print)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's use what we have learned about functions for a more useful example now. When we talked about \"Working with numbers\" in an earlier exercise, we used Python to compute a Coulomb interaction between charges at a given distance. At this point we needed to change the parameters manually, if we wanted to get the result for a different value, e.g. another distance. A function can help us here to make the calculation convenient for any given value." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "def get_force_coulomb(r, q1=1.602e-19, q2=1.602e-19, k=9e9):\n", " \"\"\"Compute Coulomb interaction\n", " \n", " Uses $F = k \\frac{q_1 q_2}{r^2}$\n", " \n", " Args:\n", " r (float): Distance (m)\n", " \n", " Keyword args:\n", " q1, q2 (float): Charges of interacting particles (C).\n", " Defaults to elemental charges.\n", " k (float): Force constant of the medium (N m$^2$ C$^{−2}$).\n", " Defaults to vacuum.\n", " \"\"\"\n", "\n", " return (k * q1 * q2) / r**2 # Calculate force" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can calculate the interaction for a whole range of values and in other contexts without much code re-writing." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.00e-10 m: 2.31e-08 N\n", "2.00e-10 m: 5.77e-09 N\n", "3.00e-10 m: 2.57e-09 N\n", "4.00e-10 m: 1.44e-09 N\n", "5.00e-10 m: 9.24e-10 N\n", "6.00e-10 m: 6.42e-10 N\n", "7.00e-10 m: 4.71e-10 N\n", "8.00e-10 m: 3.61e-10 N\n", "9.00e-10 m: 2.85e-10 N\n", "1.00e-09 m: 2.31e-10 N\n" ] } ], "source": [ "# Generate 10 values in the open interval (0.1, 1) nm\n", "r = [r * 0.1 * 1e-9 for r in range(1, 11)]\n", "\n", "for r_ in r:\n", " print(f\"{r_:.2e} m: {get_force_coulomb(r_):.2e} N\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Advanced" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Scopes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When we deal with functions we need to beware of scopes, that means we need to know\n", "about which variable is defined where. So far, when we assigned a value to a variable,\n", "this variable could be accessed from everywhere in our Python session. We say, they \n", "were *globally* defined or *global* variables. When we define variables within functions, however,\n", "these are only valid within this function. The variable `s` for example used within our `repeat_print` function,\n", "has no meaning outside this function." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "ename": "NameError", "evalue": "name 's' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ms\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mNameError\u001b[0m: name 's' is not defined" ] } ], "source": [ "print(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "While we can access global variables from within functions, variables created within functions are only\n", "*locally* available." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] } ], "source": [ "def use_global():\n", " print(x)\n", "\n", "x = 1\n", "use_global()" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\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)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0muse_local\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mNameError\u001b[0m: name 'y' is not defined" ] } ], "source": [ "def use_local():\n", " y = 1\n", " print(y)\n", "\n", "use_local()\n", "print(y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Be careful with the use of global variables within your functions! When a function relies on a global variable it is more dependent on the context in which it is used and less re-usable in other situations. As a rule of thumb, a proper function should receive everything it needs as an argument and return the outcome of its execution as a return value. Side-effects as modifying global variables should be avoided if possible to make your functions clean and general." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "**Advanced:** There are of course cases where global variables may be useful, for example when you have program-wide physical constants or settings defined. Be aware, that there is, however, no (easy) way to protect global data from changing in Python. Consider the use of local variables first, before you make your functions depend on globals. Passing a big data structure to a function to be modified locally is unproblematic, by the way, as Python passes objects essentially by reference. There is no copying of data involved and basically no performance issue with using local variables over globals.\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When we define a local variable within a function, that has been also defined globally, the local value takes precedence. Precisely, Python creates a local variable and uses this instead of the global one." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n", "1\n" ] } ], "source": [ "def use_local_instead_of_global():\n", " x = 2\n", " print(x)\n", "\n", "x = 1\n", "use_local_instead_of_global()\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A common mistake, leading to a strange error, is to try to modify a globally defined object from within a function with a statement that includes an assignment." ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "run_control": { "marked": true } }, "outputs": [ { "ename": "UnboundLocalError", "evalue": "local variable 'string' referenced before assignment", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mUnboundLocalError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mstring\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"ABC\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mcant_do_this\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstring\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m\u001b[0m in \u001b[0;36mcant_do_this\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mcant_do_this\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mstring\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mstring\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreplace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"ABC\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"XYZ\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mstring\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"ABC\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mcant_do_this\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mUnboundLocalError\u001b[0m: local variable 'string' referenced before assignment" ] } ], "source": [ "def cant_do_this():\n", " string = string.replace(\"ABC\", \"XYZ\")\n", "\n", "string = \"ABC\"\n", "cant_do_this()\n", "print(string)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this case the `string =` statements tells Python to create the local variable `string`. But at the same time `string.replace()` requires that `string` already exists. While `string` exists globally, we just said that we want to use `string` as a local variable. Python can not handle this and raises an error. You can, however, modify global objects from within functions without local assignment:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1]\n" ] } ], "source": [ "def can_do_this():\n", " list_.append(1)\n", " \n", "list_ = []\n", "can_do_this()\n", "print(list_)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also circumvent the local/global misunderstanding of Python and avoid the `UnboundLocalError` by stating explicitly to use the global object. In this case Python does not create a local variable `string` on assignments." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "XYZ\n" ] } ], "source": [ "def now_can_do_this():\n", " global string\n", " string = string.replace(\"ABC\", \"XYZ\")\n", "\n", "string = \"ABC\"\n", "now_can_do_this()\n", "print(string)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "**Note:** It is sometimes helpful in general to avoid naming conflicts between global or local variables in the first place, e.g. by choosing generic place-holders as arguments to functions and descriptive names for variables outside functions. In our `get_force_coulomb` example we used `r` in three different roles: as local variable, as global sequence, and as control variable in a list comprehension. We could have chosen three distinct names to make their role more clear. \n", "You can also choose to mark global variables with a leading underscore (`_globvar`) or to put variables supposed to be static constants in all uppercase (`OUTPUT`). The naming convention section of [PEP8](https://www.python.org/dev/peps/pep-0008/#naming-conventions) is a good standard reference if you want to learn more.\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Scopes can be confusing at times, in particular when scopes are nested. The global scope is always the outermost layer in which variables can be defined (the session- or module-level). The local scope is always the innermost layer, enclosed by the lowest level function." ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I am global\n", "I am local to 'demonstrate_scopes'\n", "I am local to 'modify_global'\n", "I was changed by 'modify_global'\n" ] } ], "source": [ "def demonstrate_scopes():\n", " \n", " x = \"I am local to 'demonstrate_scopes'\"\n", " \n", " def modify_global():\n", " global x\n", " x = \"I was changed by 'modify_global'\"\n", " \n", " y = \"I am local to 'modify_global'\"\n", " print(y) \n", " \n", " print(x)\n", " modify_global()\n", " \n", "x = \"I am global\"\n", "print(x)\n", "demonstrate_scopes()\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Between the local and the global layer, \n", "Python does also know the non-local layer. It addresses the next higher enclosing scope seen from the current local scope. You may not need this anytime soon in practice but it helps to understand scopes and where variables are valid. Let's end this tutorial with an advanced example on this." ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I am global\n", "I am local to 'demonstrate_scopes'\n", "I was changed by 'modify_non_local'\n", "I was changed by 'modify_non_local'\n", "I was changed by 'modify_global'\n" ] } ], "source": [ "def demonstrate_scopes():\n", " x = \"I am local to 'demonstrate_scopes'\"\n", " \n", " def modifiy_non_local():\n", " nonlocal x\n", " x = \"I was changed by 'modify_non_local'\"\n", "\n", " def modify_global():\n", " global x\n", " x = \"I was changed by 'modify_global'\"\n", " \n", " print(x)\n", " modifiy_non_local()\n", " print(x)\n", " modify_global()\n", " print(x)\n", " \n", "x = \"I am global\"\n", "print(x)\n", "demonstrate_scopes()\n", "print(x)" ] } ], "metadata": { "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.6.10" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": true, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": { "height": "calc(100% - 180px)", "left": "10px", "top": "150px", "width": "165px" }, "toc_section_display": true, "toc_window_display": false }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }