{ "cells": [ { "cell_type": "markdown", "id": "eb089599", "metadata": {}, "source": [ "# Introduction to Python" ] }, { "cell_type": "markdown", "id": "fd239b39", "metadata": {}, "source": [ "This notebook offers a very short overview and introduction to Python.\n", "Object oriented programming is postponed to the next lecture." ] }, { "cell_type": "markdown", "id": "4077a0fd", "metadata": {}, "source": [ "## 1. Control and Data Structures" ] }, { "cell_type": "markdown", "id": "a0da4610", "metadata": {}, "source": [ "Python is dynamically typed, interpreted. As a framework language, it comes with batteries included.\n", "Python supports modular and object oriented programming." ] }, { "cell_type": "markdown", "id": "e4bd2fb0", "metadata": {}, "source": [ "### 1.1 REPL, variables and types" ] }, { "cell_type": "markdown", "id": "3f7b6fea", "metadata": {}, "source": [ "The first instruction one tries in any programming language is the \"Hello World!\" print statement." ] }, { "cell_type": "code", "execution_count": 1, "id": "b6e5c43c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello World!\n" ] } ], "source": [ "print(\"Hello World!\")" ] }, { "cell_type": "markdown", "id": "4dce428a", "metadata": {}, "source": [ "As an interpreted language, the interpreter runs a Read-Eval-Print Loop, abbreviated as REPL." ] }, { "cell_type": "markdown", "id": "8f241a9a", "metadata": {}, "source": [ "Every variable has a type, even though in the dynamic typing system, we do not need to declare the type." ] }, { "cell_type": "code", "execution_count": 2, "id": "5913003f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "float" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = 3.1415\n", "type(x)" ] }, { "cell_type": "markdown", "id": "247fcc13", "metadata": {}, "source": [ "And every variable has a string representation." ] }, { "cell_type": "code", "execution_count": 3, "id": "3227dba2", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'3.1415'" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "str(x)" ] }, { "cell_type": "markdown", "id": "b3693813", "metadata": {}, "source": [ "The inverse to the ``str()`` function is ``eval()``, so can evaluate a string." ] }, { "cell_type": "code", "execution_count": 4, "id": "102fdbc3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.1415\n" ] }, { "data": { "text/plain": [ "3.1415" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sx = str(x)\n", "print(sx)\n", "eval(sx)" ] }, { "cell_type": "markdown", "id": "e69cc51d", "metadata": {}, "source": [ "A variable has a value and an address." ] }, { "cell_type": "code", "execution_count": 5, "id": "b42a8e28", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2147143057712" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = 3\n", "id(x)" ] }, { "cell_type": "markdown", "id": "db7ec874", "metadata": {}, "source": [ "In Python, we say that the name ``x`` refers to the object ``3``." ] }, { "cell_type": "markdown", "id": "b06a6f44", "metadata": {}, "source": [ "As a technical note, in C implementations of Python, we can *dereference* and obtain the value of a variable via its reference." ] }, { "cell_type": "code", "execution_count": 6, "id": "81e395a5", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3.1415" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = 3.1415\n", "ix = id(x)\n", "from ctypes import cast, py_object\n", "cast(ix, py_object).value" ] }, { "cell_type": "markdown", "id": "4f9cdcf9", "metadata": {}, "source": [ "### 1.2 elementary and composite types" ] }, { "cell_type": "markdown", "id": "400599dc", "metadata": {}, "source": [ "The type of a variable determines the kind of operations that can be performed on that variable. We distinguish between elementary and composite types. Examples of elementary types are ``float`` (floating-point numbers), ``int`` (integers), ``bool`` (Boolean or True/False numbers), and ``str`` (strings)." ] }, { "cell_type": "markdown", "id": "5906af7b", "metadata": {}, "source": [ "The most common composite types are\n", "\n", "1. A *tuple* is a sequence of fixed length. For example, a complex number has real and imaginary part.\n", "\n", "2. A *list* is a mutuable sequence, of variable length. The items in a list can be of different types.\n", "\n", "3. A *dictionary* is a lookup table. An item in a dictionary has an index and a value. A typical application of a dictionary is a frequence table, say of words in a text. The index is the word and the value is the number of occurrences of the word in the text." ] }, { "cell_type": "markdown", "id": "36d6baf9", "metadata": {}, "source": [ "The title of the classical textbook of Niklaus Wirth is *programs = algorithms + data structures*. And we can draw an analogy between the three common composite data types (tuple, list, dictionary) and the three common control structures (sequence, loop, if else)." ] }, { "cell_type": "markdown", "id": "a2685d5b", "metadata": {}, "source": [ "| control structure | data structure\n", "|-------------------|---------------\n", "| sequence | tuple\n", "| if else | dictionary\n", "| loop | list" ] }, { "cell_type": "markdown", "id": "ad627175", "metadata": {}, "source": [ "A program transforms data and all data are sequences of bits, or bit tuples." ] }, { "cell_type": "markdown", "id": "8283b329", "metadata": {}, "source": [ "Consider the tuple assignment:" ] }, { "cell_type": "code", "execution_count": 7, "id": "c423d110", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n" ] } ], "source": [ "(a, b) = (1, 2)\n", "print(a)\n", "print(b)" ] }, { "cell_type": "markdown", "id": "7d38c3c2", "metadata": {}, "source": [ "With a tuple assignment, we can swap the values of variables, that ``a`` will refer to ``2`` and ``b`` to ``1``, *without having to use a temporary variable.*" ] }, { "cell_type": "code", "execution_count": 8, "id": "6a3b6da5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n", "1\n" ] } ], "source": [ "(a, b) = (b, a)\n", "print(a)\n", "print(b)" ] }, { "cell_type": "markdown", "id": "b186f176", "metadata": {}, "source": [ "To illustrate the analogy between dictionaries and if else statements, consider the following." ] }, { "cell_type": "code", "execution_count": 9, "id": "f7e3575e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "good afternoon\n" ] } ], "source": [ "import time\n", "hour = time.localtime()[3]\n", "if hour < 12:\n", " print(\"good morning\")\n", "else:\n", " print(\"good afternoon\")" ] }, { "cell_type": "markdown", "id": "8dea310e", "metadata": {}, "source": [ "A dictionary is a set of keys and values. The keys store the conditions, the values hold the arguments of the ``print`` statement in the above if else." ] }, { "cell_type": "code", "execution_count": 10, "id": "d308435c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'good afternoon'" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d = {True: \"good morning\", False: \"good afternoon\"}\n", "d[hour < 12]" ] }, { "cell_type": "markdown", "id": "13f14482", "metadata": {}, "source": [ "We can ask for all items in a dictionary, for all keys, and all values, as illustrated below." ] }, { "cell_type": "code", "execution_count": 11, "id": "b1d44723", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "dict_items([(True, 'good morning'), (False, 'good afternoon')])" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d.items()" ] }, { "cell_type": "code", "execution_count": 12, "id": "ffc53356", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "dict_keys([True, False])" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d.keys()" ] }, { "cell_type": "code", "execution_count": 13, "id": "c3a677de", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "dict_values(['good morning', 'good afternoon'])" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d.values()" ] }, { "cell_type": "markdown", "id": "1e0a5942", "metadata": {}, "source": [ "We can convert the values to a list, as shown below." ] }, { "cell_type": "code", "execution_count": 14, "id": "8ed2652f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['good morning', 'good afternoon']" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(d.values())" ] }, { "cell_type": "markdown", "id": "16445b0c", "metadata": {}, "source": [ "### 1.3 list comprehensions" ] }, { "cell_type": "markdown", "id": "1f92abbc", "metadata": {}, "source": [ "Loops and lists are connected through *list comprehensions*. Assume we want to see all odd numbers less than ten." ] }, { "cell_type": "code", "execution_count": 15, "id": "fd2f3bc4", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 3, 5, 7, 9]" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "L = [x for x in range(1, 11, 2)]\n", "L" ] }, { "cell_type": "markdown", "id": "cf53ed05", "metadata": {}, "source": [ "This is equivalent to the more commonly used loop construction in many other languages." ] }, { "cell_type": "code", "execution_count": 16, "id": "104af0be", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 3, 5, 7, 9]" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "L = []\n", "for x in range(1, 11, 2):\n", " L.append(x)\n", "L" ] }, { "cell_type": "markdown", "id": "07d919ac", "metadata": {}, "source": [ "The ``range(1, 11, 2)`` starts at ``1``, ends at ``10`` (not 11) and proceeds with increments of ``2``." ] }, { "cell_type": "markdown", "id": "8c7b4f89", "metadata": {}, "source": [ "Strings are lists of characters. Let us illustrate this with the decimal expansion of pi." ] }, { "cell_type": "code", "execution_count": 17, "id": "4d16ace6", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3.141592653589793" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from math import pi\n", "pi" ] }, { "cell_type": "code", "execution_count": 18, "id": "b8325f8d", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "str" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spi = str(pi)\n", "type(spi)" ] }, { "cell_type": "markdown", "id": "208e1eda", "metadata": {}, "source": [ "Let us take a slice of ``spi``, the first eight characters after the ``.``, starting at position 2 and ending at 9." ] }, { "cell_type": "code", "execution_count": 19, "id": "82ed3998", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'14159265'" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "slice = spi[2:10]\n", "slice" ] }, { "cell_type": "code", "execution_count": 20, "id": "6e536d13", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['1', '4', '1', '5', '9', '2', '6', '5']" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "d = [c for c in slice]\n", "d" ] }, { "cell_type": "markdown", "id": "497d0ce4", "metadata": {}, "source": [ "To convert now to integers, we execute another list comprehension." ] }, { "cell_type": "code", "execution_count": 21, "id": "d476ba1e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 4, 1, 5, 9, 2, 6, 5]" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[int(x) for x in d]" ] }, { "cell_type": "markdown", "id": "d0fac871", "metadata": {}, "source": [ "### 1.4 sharing references" ] }, { "cell_type": "markdown", "id": "e7a18702", "metadata": {}, "source": [ "In the C implementation of Python, there is a (very technical) way to dereference, to obtain the value via its reference. With lists, we have a tool to manipulate values through references." ] }, { "cell_type": "code", "execution_count": 22, "id": "73ef74dd", "metadata": {}, "outputs": [], "source": [ "x = 3" ] }, { "cell_type": "markdown", "id": "44fccc1f", "metadata": {}, "source": [ "The effect of ``x = 3`` is that ``x`` refers to the object ``3``, of type ``int``." ] }, { "cell_type": "code", "execution_count": 23, "id": "2946f152", "metadata": {}, "outputs": [], "source": [ "L = [3]" ] }, { "cell_type": "markdown", "id": "558f2f8a", "metadata": {}, "source": [ "The effect of ``L = [3]`` is that the name ``L`` refers to a list where the name ``L[0]`` refers to the object ``3``. " ] }, { "cell_type": "markdown", "id": "84dde487", "metadata": {}, "source": [ "How is ``x = 3`` now different from ``L = [3]``? Well we can change the content of ``L`` as follows." ] }, { "cell_type": "code", "execution_count": 24, "id": "e5bd5161", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[3]" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "K = L\n", "K" ] }, { "cell_type": "markdown", "id": "e3118e2f", "metadata": {}, "source": [ "After ``K = L``, we say that the name ``K`` refers to ``L`` but this means that both ``K`` and ``L`` refer to the same list ``[3]``." ] }, { "cell_type": "code", "execution_count": 25, "id": "24e87fa5", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[4]" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "K[0] = 4\n", "L" ] }, { "cell_type": "markdown", "id": "8ec7f0a9", "metadata": {}, "source": [ "We have change ``L`` through ``K``, because ``K`` and ``L`` share references." ] }, { "cell_type": "markdown", "id": "c1caf4f4", "metadata": {}, "source": [ "An important application of reference sharing is in *call by reference* when writing functions." ] }, { "cell_type": "markdown", "id": "e1886adc", "metadata": {}, "source": [ "## 2. Functions and Modules" ] }, { "cell_type": "markdown", "id": "d40d6da6", "metadata": {}, "source": [ "Large programs consist of modules. A module is a collection of functions." ] }, { "cell_type": "markdown", "id": "bcdb90bb", "metadata": {}, "source": [ "### 2.1 defining functions" ] }, { "cell_type": "markdown", "id": "8164ac45", "metadata": {}, "source": [ "Short functions can be defined in one line with ``lambda``. For example to define $f(x) = x^2$, we can do the following." ] }, { "cell_type": "code", "execution_count": 26, "id": "2517c75c", "metadata": {}, "outputs": [], "source": [ "fun = lambda x: x**2" ] }, { "cell_type": "code", "execution_count": 27, "id": "bcf87751", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fun(2)" ] }, { "cell_type": "markdown", "id": "3ff5c491", "metadata": {}, "source": [ "The general way to define a function is with ``def`` as illustrated below." ] }, { "cell_type": "code", "execution_count": 28, "id": "d102ab6d", "metadata": {}, "outputs": [], "source": [ "def funtoo(x):\n", " \"\"\"\n", " Returns the square of x.\n", " \"\"\"\n", " return x**2" ] }, { "cell_type": "code", "execution_count": 29, "id": "8bcb336f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "funtoo(2)" ] }, { "cell_type": "markdown", "id": "d1004e5d", "metadata": {}, "source": [ "Every function has a name, its input and return values may be empty. The documentation string is optional but recommended." ] }, { "cell_type": "code", "execution_count": 30, "id": "e5f58369", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on function funtoo in module __main__:\n", "\n", "funtoo(x)\n", " Returns the square of x.\n", "\n" ] } ], "source": [ "help(funtoo)" ] }, { "cell_type": "markdown", "id": "db4a4ddb", "metadata": {}, "source": [ "### 2.2 call by value and call by reference" ] }, { "cell_type": "markdown", "id": "08fe53a4", "metadata": {}, "source": [ "By default, a function does not alter its input argument(s) and we have the *call by value* mechanism. If we give the argument a list on input, then we can alter the content of the list, as the function call pass the reference to the list, and we apply *call by reference*. The next function illustrates the call by reference mechanism." ] }, { "cell_type": "code", "execution_count": 31, "id": "055468e5", "metadata": {}, "outputs": [], "source": [ "def funthree(arg):\n", " \"\"\"\n", " Squares arg[0].\n", " \"\"\"\n", " arg[0] = arg[0]**2" ] }, { "cell_type": "code", "execution_count": 32, "id": "bc593e33", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[9]" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "L = [3]\n", "funthree(L)\n", "L" ] }, { "cell_type": "markdown", "id": "561d4bcd", "metadata": {}, "source": [ "Although object oriented programming will be discussed in greater detail in the next lecture, consider the following." ] }, { "cell_type": "code", "execution_count": 33, "id": "f0b90caf", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['__add__',\n", " '__class__',\n", " '__class_getitem__',\n", " '__contains__',\n", " '__delattr__',\n", " '__delitem__',\n", " '__dir__',\n", " '__doc__',\n", " '__eq__',\n", " '__format__',\n", " '__ge__',\n", " '__getattribute__',\n", " '__getitem__',\n", " '__gt__',\n", " '__hash__',\n", " '__iadd__',\n", " '__imul__',\n", " '__init__',\n", " '__init_subclass__',\n", " '__iter__',\n", " '__le__',\n", " '__len__',\n", " '__lt__',\n", " '__mul__',\n", " '__ne__',\n", " '__new__',\n", " '__reduce__',\n", " '__reduce_ex__',\n", " '__repr__',\n", " '__reversed__',\n", " '__rmul__',\n", " '__setattr__',\n", " '__setitem__',\n", " '__sizeof__',\n", " '__str__',\n", " '__subclasshook__',\n", " 'append',\n", " 'clear',\n", " 'copy',\n", " 'count',\n", " 'extend',\n", " 'index',\n", " 'insert',\n", " 'pop',\n", " 'remove',\n", " 'reverse',\n", " 'sort']" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dir(L)" ] }, { "cell_type": "markdown", "id": "5676934c", "metadata": {}, "source": [ "Asking ``dir`` on ``L`` exposed all operations that are defined on ``L``, which is an instance of the class ``list``.\n", "The last operation is ``sort``. Now ``sort`` is a method, not a function. To apply ``sort`` on a list ``L``, we have to write ``L.sort()``, not ``sort(L)``. Let us illustrate this." ] }, { "cell_type": "code", "execution_count": 34, "id": "730700cf", "metadata": {}, "outputs": [ { "ename": "NameError", "evalue": "name 'sort' is not defined", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_50292/3678058418.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0mL\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m4\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m5\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0msort\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mL\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mNameError\u001b[0m: name 'sort' is not defined" ] } ], "source": [ "L = [3, 1, 4, 1, 5]\n", "sort(L)" ] }, { "cell_type": "code", "execution_count": 35, "id": "89eba5cf", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 1, 3, 4, 5]" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "L.sort()\n", "L" ] }, { "cell_type": "markdown", "id": "d901d79b", "metadata": {}, "source": [ "See, the ``sort`` is a method which changes the object ``L`` it applies to." ] }, { "cell_type": "markdown", "id": "414c68c7", "metadata": {}, "source": [ "If we really wanted a function to sort the elements in a list, then we can define one, in one line." ] }, { "cell_type": "code", "execution_count": 36, "id": "c44ee6f4", "metadata": {}, "outputs": [], "source": [ "mysort = lambda L: L.sort()" ] }, { "cell_type": "code", "execution_count": 37, "id": "bc85f4ff", "metadata": {}, "outputs": [], "source": [ "K = [3, 1, 4, 1, 5]" ] }, { "cell_type": "code", "execution_count": 38, "id": "2b834305", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[3, 1, 4, 1, 5]" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "K" ] }, { "cell_type": "code", "execution_count": 39, "id": "8fa56a23", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 1, 3, 4, 5]" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "mysort(K)\n", "K" ] }, { "cell_type": "markdown", "id": "e14afaad", "metadata": {}, "source": [ "### 2.3 modules" ] }, { "cell_type": "markdown", "id": "65a84086", "metadata": {}, "source": [ "Functions stored in one file define a *module* and we use the ``import`` statement to import the module." ] }, { "cell_type": "code", "execution_count": 40, "id": "e9990984", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['__doc__',\n", " '__loader__',\n", " '__name__',\n", " '__package__',\n", " '__spec__',\n", " 'acos',\n", " 'acosh',\n", " 'asin',\n", " 'asinh',\n", " 'atan',\n", " 'atanh',\n", " 'cos',\n", " 'cosh',\n", " 'e',\n", " 'exp',\n", " 'inf',\n", " 'infj',\n", " 'isclose',\n", " 'isfinite',\n", " 'isinf',\n", " 'isnan',\n", " 'log',\n", " 'log10',\n", " 'nan',\n", " 'nanj',\n", " 'phase',\n", " 'pi',\n", " 'polar',\n", " 'rect',\n", " 'sin',\n", " 'sinh',\n", " 'sqrt',\n", " 'tan',\n", " 'tanh',\n", " 'tau']" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import cmath\n", "dir(cmath)" ] }, { "cell_type": "markdown", "id": "10018b46", "metadata": {}, "source": [ "With ``dir`` we see the functions *exported* by the module. To use the ``sqrt`` of the ``cmath`` module, we do the following:" ] }, { "cell_type": "code", "execution_count": 41, "id": "ed9fad46", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2j" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cmath.sqrt(-4)" ] }, { "cell_type": "markdown", "id": "eea1fe93", "metadata": {}, "source": [ "The ``c`` in ``cmath`` stands for ``complex`` and ``j`` is the imaginary unit." ] }, { "cell_type": "markdown", "id": "fcbb4baa", "metadata": {}, "source": [ "To avoid confusion with the ``sqrt`` of the ``math`` module, it is better to call a function with its module name." ] } ], "metadata": { "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", "version": "3.10.1" } }, "nbformat": 4, "nbformat_minor": 5 }