{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Syntaxe v Pythonu je velmi jednoduchá (alespoň pokud to jde). Python je bezesporu jedním ze syntakticky nejpřirozenějších jazyků vůbec.\n", "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Komentáře" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Komentáře v Pythonu jsou velice jednoduché. My je v celém kurzu používáme celkem hustě, takže jen pár ukázek:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'V Pythonu nejsou žádné víceřádkové komentáře, které by\\nodpovídaly /* */ z C++ či Javy, nicméně často se místo nich\\npoužívají víceřádkové řetězce, které se jen nepřiřadí do\\nžádné proměnné a dále nepoužijí. Obvyklé je to zejména u\\ntzv. docstringů (viz dále).'" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# - Takto vypadá komentář.\n", "# - Začíná vždy znakem \"#\" (hash)\n", "# - Je víceméně ekvivalentní // v C++\n", "\n", "a = 1 + 2 # Komentář na řádku s kódem\n", "\n", "\"\"\"V Pythonu nejsou žádné víceřádkové komentáře, které by\n", "odpovídaly /* */ z C++ či Javy, nicméně často se místo nich\n", "používají víceřádkové řetězce, které se jen nepřiřadí do\n", "žádné proměnné a dále nepoužijí. Obvyklé je to zejména u\n", "tzv. docstringů (viz dále).\"\"\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Jednoduché příkazy\n", "Zkuste si následující příkazy a nějaké jejich obměny." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "data": { "text/plain": [ "1.55" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = 1 + 1.1 / 2 # jednoduchý výpočet, vytvoření a přiřazení do proměnné a\n", "print(type(a)) # výpis do terminálu (stdout)\n", "a # IPython ukáže výstup, pokud ho neuložíme do proměnné" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello world!\n", "type(a) = , len(a) = 12\n" ] } ], "source": [ "a = \"Hello\" + \" world!\" # jednoduchá práce s řetězci\n", "print(a)\n", "print(\"type(a) = %s, len(a) = %i\" % (type(a), len(a))) # formátovaný výstup" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a = 0.707\n" ] } ], "source": [ "import math # chceme načíst vestavěný modul math\n", "a = math.cos(math.pi / 4) # použijeme funkci cos a konstantu pi\n", "print('a = %.3g' % a)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a = 0.707\n" ] } ], "source": [ "from math import sin, pi # import pouze některých položek\n", "a = sin(pi / 4)\n", "print('a = %.3g' % a)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "ename": "NameError", "evalue": "name 'cos' 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[0ma\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcos\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpi\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# tohle asi nebude fungovat --> výjimka\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mNameError\u001b[0m: name 'cos' is not defined" ] } ], "source": [ "a = cos(pi / 2) # tohle asi nebude fungovat --> výjimka" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Některé důležité vestavěné funkce \n", "Vestavěných funkcí, nebo [Built-in functions](http://docs.python.org/2/library/functions.html), je v Pythonu minimum. Zde zmíníme některé z nich (s některými jsme se už setkali):\n", "\n", "* `dir` -- seznam jmen (funkcí, proměnných, metod) v daném kontextu\n", "* `eval` -- vrátí hodnotu výrazu zadanou řetězcem (to je možné, protože Python je interpretovaný jazyk)\n", "* `help` -- nápověda (neboli zobrazení 'docstring'\n", "* `len` -- délka (počet položek) proměnné (řetězce, pole apod.)\n", "* `open` -- otevření souboru\n", "* `print` -- výpis řetězce do stream\n", "* `raw_input` -- načtení vstupu od uživatele (stdin)\n", "* `str`, `repr` -- text reprezentující daný objekt\n", "* `type` -- vrátí typ argumentu\n", "\n", "Blíže se s těmito a dalšími vestavěnými funkcemi se seznámíme brzy." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['In', 'Out', '_', '_1', '_2', '__', '___', '__builtin__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', '_dh', '_i', '_i1', '_i2', '_i3', '_i4', '_i5', '_i6', '_i7', '_ih', '_ii', '_iii', '_oh', 'a', 'exit', 'get_ipython', 'math', 'pi', 'quit', 'sin']\n", "\n", "['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']\n" ] } ], "source": [ "print(str(dir()) + \"\\n\")\n", "print(repr(dir(\"a\")))" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a * 4 = 8, a = 2\n" ] } ], "source": [ "a = 2\n", "e = input(\"Zadejte výraz s proměnnou a: \")\n", "print(\"%s = %s, a = %s\" % (e, str(eval(e)), str(a))) # použití funkce eval na předem neznámý výraz" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Přehled operátorů v Pythonu\n", "\n", " + - * @ ** / // %\n", " << >> & | ^ ~\n", " < > <= >= == != <>\n", " or and not\n", " is is not in not in\n", "\n", "## Klíčová slova\n", "\n", " and del from not while\n", " as elif global or with\n", " assert else if pass yield\n", " break except import print\n", " class exec in raise\n", " continue finally is return\n", " def for lambda try" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Podmínky a další bloky v Pythonu\n", "V Pythonu začínají funkční bloky (neboli složené výrazy - [compound statements](http://docs.python.org/2/reference/compound_stmts.html) klíčovým slovem, následovaným **dvojtečkou** a vymezují se **odsazením** (tj. žádné begin-end nebo dvojice závorek). Toto odsazení je libovolné, musí být ale konzistentní (tj. vždy stejný počet mezer). Silně se doporučuje používat **čtyři mezery**, jak říká PEP 8 ([PEP 8 -- Style Guide for Python Code](http://www.python.org/dev/peps/pep-0008/#indentation)). Tento dokument obsahuje i další důležité *konvence*, např. pojmenovávání proměnných, funkcí, tříd atd., používání mezer a další. Ukážeme si to na `if` bloku." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Platí 2 > 1\n", "Platí 2 > 1 a neplatí 1 > 2\n" ] } ], "source": [ "if 2 > 1:\n", " print(\"Platí 2 > 1\")\n", " if 1 > 2:\n", " print(\"Platí 2 > 1 a 1 > 2\")\n", " else:\n", " print(\"Platí 2 > 1 a neplatí 1 > 2\")\n", "else:\n", " print(\"Neplatí 2 > 1\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "V Pythonu máme k dispozici trojici podmínkových klíčových slov `if` - `elif` - `else`. Zato zde nenajdete nic, co by se podobalo klíčovým slovům `switch`/`case` z jiných jazyků (musíte si vystačit s `if`, `elif`, `else`)." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "To dokážu spočítat na jedné ruce\n" ] } ], "source": [ "a = 5\n", "if a > 10:\n", " print(\"Tolik prstů na rukou nemáme\")\n", "elif a > 5:\n", " print(\"Na to potřebujeme prsty na obou rukách\")\n", "elif a >= 0:\n", " print(\"To dokážu spočítat na jedné ruce\")\n", "else:\n", " print(\"Záporná čísla neumím\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pro `while` blok platí stejná pravidla pro odsazení:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n", "4\n" ] } ], "source": [ "a = 0\n", "while a < 5:\n", " print(a)\n", " a += 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`while` blok (stejně tak `for`, o tom ale bude řeč později, protože funguje krapet jinak než v jiných běžných jazycích) může mít také `else` část, která se spustí ve chvíli, kdy je podmínka `False`. " ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a = 0\n", "a = 1\n", "a = 2\n", "a = 3\n", "a = 4\n", "Konec, a = 1\n" ] } ], "source": [ "a = 0\n", "while a < 5:\n", " print(\"a = %i\" % a)\n", " a += 1\n", "else:\n", " a = 1\n", "print(\"Konec, a = %i\" % a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dále existují klíčová slova `break` a `continue`. `break` přeruší cyklus, zatímco `continue` skočí na začátek další iterace, tj. přeskočí příkazy pod sebou." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a = 1\n", "a = 3\n", "a = 5\n", "Konec, a = 1\n" ] } ], "source": [ "a = 0\n", "while a < 5:\n", " a += 1\n", " # sudá čísla nebudeme vypisovat\n", " if a % 2 == 0:\n", " continue\n", " print(\"a = %i\" % a)\n", "else:\n", " a = 1\n", "print(\"Konec, a = %i\" % a)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Výsledek je: 988\n" ] } ], "source": [ "# pomocí break najdeme největší trojciferené číslo dělitelné 19ti\n", "a = 999\n", "while a > 0:\n", " if a % 19 == 0:\n", " print(\"Výsledek je: %i\" % a)\n", " break\n", " a -= 1\n", "else:\n", " # break nespustí else část\n", " print(\"Nic jsme nenašli\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Víceřádkové výrazy\n", "V Pythonu je možné dlouhé řádky rozdělit pomocí zpětného lomítka na konci řádku. Další řádek by se pak měl odsadit." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'pomoci plus vytvorime pro ukazku nejaky dlouhy retezec znaku, ktery nedava zadny velky smysl ...'" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dlouhy_nazev_promenne = \"pomoci plus vytvorime pro ukazku nejaky dlouhy retezec znaku, \" + \\\n", " \"ktery nedava zadny velky smysl ...\"\n", "dlouhy_nazev_promenne" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Použití \\ je ovšem ve většině případů zbytečné (a obecně se ndoporučuje), protože u výrazů v závorkách je zpětné lomítko nepovinné." ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "-9431767748815581066" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dlouhy_nazev_promenne = (10000000000000 + 2222222222222222 + 9999999999999999 + 3987493874 +\n", " 444444444444444 + 23987342978 + 9874 + 555555555555555555 +\n", " 987349987 - 9999999999999999999)\n", "dlouhy_nazev_promenne" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Obecně se doporučuje mít řádky kratší než 80 znaků (viz [PEP8](http://www.python.org/dev/peps/pep-0008/#maximum-line-length)), tato konvence je ale v některých případech ne zcela vyhovující. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Definice funkcí\n", "Základem pro definici funkcí je klíčové slovo `def`. Opět to ukážeme na příkladech." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello Python!\n" ] } ], "source": [ "# definice jednoduché funkce bez parametrů a návratové hodnoty\n", "def hello():\n", " print(\"Hello Python!\")\n", "# tady funkci zavoláme\n", "hello()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Taková funkce je ale celkem neužitečná, u funkcí potřebujeme obvykle vstupy a/nebo výstupy." ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello Prague!\n" ] } ], "source": [ "# what je argument funkce hello\n", "def hello(subj):\n", " phrase = \"Hello %s!\" % subj\n", " # return ukončí funkci a případně vrátí hodnotu\n", " return phrase\n", "print(hello(\"Prague\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Rozlišujeme *poziční* a *keyword* (pojmenované) argumenty. Argumenty mohou mít i *implicitní hodnoty*, čímž se stanou *nepovinnými*. " ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello Prague!\n", "Nazdar Praho!\n", "Nazdar Praho!\n" ] } ], "source": [ "# greet je argument s implicitní hodnotou\n", "def hello(subj, greet=\"Hello\"):\n", " phrase = \"%s %s!\" % (greet, subj)\n", " # return ukončí funkci a případně vrátí hodnotu\n", " return phrase\n", "# ponecháme implicitní hodnotu greet\n", "print(hello(\"Prague\"))\n", "# použijeme greet jako keyword argument\n", "# poziční argumenty musí být vždy jako první\n", "print(hello(\"Praho\", greet=\"Nazdar\"))\n", "# subj můžeme také použít jako keyword argument\n", "print(hello(greet=\"Nazdar\", subj=\"Praho\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Funkce mohou mít i proměnný počet argumentů, o tom si ale povíme později, až se naučíme používat základní kontejnery a iterace." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Cvičení:** Přepiště výpočet obsahu lichoběžníku do funkce" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Obsah lichoběžníku a=3.5, b=2.1, v=7.7 je: 21.56\n" ] } ], "source": [ "a = 3.5\n", "b = 2.1\n", "v = 77e-1\n", "S = (a + b) * v / 2\n", "print(\"Obsah lichoběžníku a=%g, b=%g, v=%g je: %g\" % (a, b, v, S))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Z toho bychom rádi funkci - doplňte:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def trapezoid_area(...): \n", " ...\n", " \n", "S = trapezoid_area(a, b, v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Vedlejší efekty u funkcí\n", "\n", "Funkce v Pythonu mohou mít vedlejší efekty, tj. mohou měnit vstupní argumenty, pokud jsou argumenty tzv. *mutable*. Co znamená mutable a immutable, se dozvíme později. V každém případě se *silně doporučuje vyhnout se funkcím s vedlejšími efekty* (pokud z pojmenování a účelu funkce jasně nevyplývá, že je má). Ukážeme si příklad funkce, která má vedlejší efekty." ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "original list\n", "['in my list']\n", "l inside the function\n", "['in my list', \"I'm here\"]\n", "x after calling the function\n", "['in my list', \"I'm here\"]\n" ] } ], "source": [ "def do_not_do_this(l):\n", " # předpokládáme, že l je list\n", " l.append(\"I'm here\")\n", " print(\"l inside the function\")\n", " print(l)\n", "print(\"original list\")\n", "x = [\"in my list\"]\n", "print(x)\n", "do_not_do_this(x)\n", "print(\"x after calling the function\")\n", "print(x)\n", "\n", "# Toto už je lepší, neboť je zřejmé, že funkce vedlejší efekty má (a jaké asi jsou).\n", "# Ale i tak by se to dalo vyřešit lépe.\n", "def insert_item_into_list(l, item):\n", " l.append(item)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nemilé překvapení nás také může čekat, pokud implicitní hodnoty nějakého parametru jsou mutable." ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['appended']\n", "['appended']\n", "['appended']\n", "['appended', 'appended']\n" ] } ], "source": [ "def foo(l=[]):\n", " # tady se mění l\n", " l.append(\"appended\")\n", " print(l)\n", "# zavoláme s explicitním argumentem\n", "foo([])\n", "# pak zavoláme s implicitní hodnotou - výsledek by měl být stejný\n", "foo()\n", "# zkusíme stejná dvě volání, očekáváme, že výsledky budou stále stejné, ale ...\n", "foo([])\n", "foo()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vedleším efektům můžeme předcházet pomocí *kopírování* (modul `copy`, některé třídy obsahují metodu `copy`). Lépe je ale přímo generovat výsledky do nové proměnné, tedy např." ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['appended']\n", "['appended']\n", "['appended']\n", "['appended']\n" ] } ], "source": [ "def foo(l=[]):\n", " p = l + [\"appended\"]\n", " print(p)\n", "# zavoláme s explicitním argumentem\n", "foo([])\n", "# pak zavoláme s implicitní hodnotou - výsledek by měl být stejný\n", "foo()\n", "# zkusíme stejná dvě volání, výsledky už snad budou stejné\n", "foo([])\n", "foo()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Použití modulů" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Jakýkoliv složitější kód (od stovek řádků výše) je obvykle dělen do tzv. modulů. Zatím je považujeme za jednoduché schránky se znovupoužitelnými funkcemi a objekty (o jejich vytváření si povíme později), nicméně už od samého počátku práce s Pythonem se bez použití (cizích) modulů neobejdeme. Celá bohatá základní knihovna Pythonu je vlastně ohromná množina modulů." ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.0\n" ] } ], "source": [ "# Načte modul \"math\" a zpřístupní objekty v něm obsažené\n", "import math\n", "# cos je funkce definovaná v modulu \"math\"\n", "print(math.cos(0))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Kromě importu modulů jako takových lze importovat i některé jejich části, v našem případě:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.0\n" ] } ], "source": [ "# Budeme s funkcí \"cos\" z modulu \"math\" zacházet, jako kdyby byla definována v aktuálním souboru\n", "from math import cos\n", "print(cos(0))\n", "\n", "# Importuje všechny objekty, které v modulu najde. Obvykle se nedoporučuje používat, protože\n", "# nevíme, co všechno modul obsahuje, a spousta pojmenovaných funkcí, tříd a proměnných by\n", "# mohla kolidovat s něčím v aktuálním skriptu.\n", "from math import *" ] } ], "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.5" } }, "nbformat": 4, "nbformat_minor": 2 }