5. Základní syntaxe#
Syntaxe v Pythonu je velmi jednoduchá (alespoň pokud to jde). Python je bezesporu jedním ze syntakticky nejpřirozenějších jazyků vůbec.
5.1. Komentáře#
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:
# - Takto vypadá komentář.
# - Začíná vždy znakem "#" (hash)
# - Je víceméně ekvivalentní // v C++
a = 1 + 2 # Komentář na řádku s kódem
"""V Pythonu nejsou žádné víceřádkové komentáře, které by
odpovídaly /* */ z C++ či Javy, nicméně často se místo nich
používají víceřádkové řetězce, které se jen nepřiřadí do
žádné proměnné a dále nepoužijí. Obvyklé je to zejména u
tzv. docstringů (viz dále)."""
'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).'
5.2. Jednoduché příkazy#
Zkuste si následující příkazy a nějaké jejich obměny.
a = 1 + 1.1 / 2 # jednoduchý výpočet, vytvoření a přiřazení do proměnné a
print(type(a)) # výpis do terminálu (stdout)
a # IPython ukáže výstup, pokud ho neuložíme do proměnné
<class 'float'>
1.55
a = "Hello" + " world!" # jednoduchá práce s řetězci
print(a)
print("type(a) = %s, len(a) = %i" % (type(a), len(a))) # formátovaný výstup
Hello world!
type(a) = <class 'str'>, len(a) = 12
import math # chceme načíst vestavěný modul math
a = math.cos(math.pi / 4) # použijeme funkci cos a konstantu pi
print('a = %.3g' % a)
a = 0.707
from math import sin, pi # import pouze některých položek
a = sin(pi / 4)
print('a = %.3g' % a)
a = 0.707
a = cos(pi / 2) # tohle asi nebude fungovat --> výjimka
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[6], line 1
----> 1 a = cos(pi / 2) # tohle asi nebude fungovat --> výjimka
NameError: name 'cos' is not defined
5.3. Některé důležité vestavěné funkce#
Vestavěných funkcí, nebo Built-in functions, je v Pythonu minimum. Zde zmíníme některé z nich (s některými jsme se už setkali):
dir
– seznam jmen (funkcí, proměnných, metod) v daném kontextueval
– vrátí hodnotu výrazu zadanou řetězcem (to je možné, protože Python je interpretovaný jazyk)help
– nápověda (neboli zobrazení ‘docstring’len
– délka (počet položek) proměnné (řetězce, pole apod.)open
– otevření souboruprint
– výpis řetězce do streamraw_input
– načtení vstupu od uživatele (stdin)str
,repr
– text reprezentující daný objekttype
– vrátí typ argumentu
Blíže se s těmito a dalšími vestavěnými funkcemi se seznámíme brzy.
print(str(dir()) + "\n")
print(repr(dir("a")))
['In', 'Out', '_', '_1', '_2', '__', '___', '__builtin__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', '__vsc_ipynb_file__', '_dh', '_i', '_i1', '_i2', '_i3', '_i4', '_i5', '_i6', '_i7', '_ih', '_ii', '_iii', '_oh', 'a', 'exit', 'get_ipython', 'math', 'open', 'pi', 'quit', 'sin']
['__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', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'removeprefix', 'removesuffix', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
a = 2
e = input("Zadejte výraz s proměnnou a: ")
print("%s = %s, a = %s" % (e, str(eval(e)), str(a))) # použití funkce eval na předem neznámý výraz
Traceback (most recent call last):
File ~/mambaforge/envs/python-fjfi/lib/python3.9/site-packages/IPython/core/interactiveshell.py:3505 in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
Cell In[8], line 3
print("%s = %s, a = %s" % (e, str(eval(e)), str(a))) # použití funkce eval na předem neznámý výraz
File <string>
^
SyntaxError: unexpected EOF while parsing
5.4. Přehled operátorů v Pythonu#
+ - * @ ** / // %
<< >> & | ^ ~
< > <= >= == != <>
or and not
is is not in not in
5.5. Klíčová slova#
and del from not while
as elif global or with
assert else if pass yield
break except import print
class exec in raise
continue finally is return
def for lambda try
5.6. Podmínky a další bloky v Pythonu#
V Pythonu začínají funkční bloky (neboli složené výrazy - compound statements 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). 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.
if 2 > 1:
print("Platí 2 > 1")
if 1 > 2:
print("Platí 2 > 1 a 1 > 2")
else:
print("Platí 2 > 1 a neplatí 1 > 2")
else:
print("Neplatí 2 > 1")
Platí 2 > 1
Platí 2 > 1 a neplatí 1 > 2
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
).
a = 5
if a > 10:
print("Tolik prstů na rukou nemáme")
elif a > 5:
print("Na to potřebujeme prsty na obou rukách")
elif a >= 0:
print("To dokážu spočítat na jedné ruce")
else:
print("Záporná čísla neumím")
To dokážu spočítat na jedné ruce
Pro while
blok platí stejná pravidla pro odsazení:
a = 0
while a < 5:
print(a)
a += 1
0
1
2
3
4
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
.
a = 0
while a < 5:
print("a = %i" % a)
a += 1
else:
a = 1
print("Konec, a = %i" % a)
a = 0
a = 1
a = 2
a = 3
a = 4
Konec, a = 1
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.
a = 0
while a < 5:
a += 1
# sudá čísla nebudeme vypisovat
if a % 2 == 0:
continue
print("a = %i" % a)
else:
a = 1
print("Konec, a = %i" % a)
a = 1
a = 3
a = 5
Konec, a = 1
# pomocí break najdeme největší trojciferené číslo dělitelné 19ti
a = 999
while a > 0:
if a % 19 == 0:
print("Výsledek je: %i" % a)
break
a -= 1
else:
# break nespustí else část
print("Nic jsme nenašli")
Výsledek je: 988
5.7. Víceřádkové výrazy#
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.
dlouhy_nazev_promenne = "pomoci plus vytvorime pro ukazku nejaky dlouhy retezec znaku, " + \
"ktery nedava zadny velky smysl ..."
dlouhy_nazev_promenne
'pomoci plus vytvorime pro ukazku nejaky dlouhy retezec znaku, ktery nedava zadny velky smysl ...'
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é.
dlouhy_nazev_promenne = (10000000000000 + 2222222222222222 + 9999999999999999 + 3987493874 +
444444444444444 + 23987342978 + 9874 + 555555555555555555 +
987349987 - 9999999999999999999)
dlouhy_nazev_promenne
-9431767748815581066
Obecně se doporučuje mít řádky kratší než 80 znaků (viz PEP8), tato konvence je ale v některých případech ne zcela vyhovující.
5.8. Definice funkcí#
Základem pro definici funkcí je klíčové slovo def
. Opět to ukážeme na příkladech.
# definice jednoduché funkce bez parametrů a návratové hodnoty
def hello():
print("Hello Python!")
# tady funkci zavoláme
hello()
Hello Python!
Taková funkce je ale celkem neužitečná, u funkcí potřebujeme obvykle vstupy a/nebo výstupy.
# what je argument funkce hello
def hello(subj):
phrase = "Hello %s!" % subj
# return ukončí funkci a případně vrátí hodnotu
return phrase
print(hello("Prague"))
Hello Prague!
Rozlišujeme poziční a keyword (pojmenované) argumenty. Argumenty mohou mít i implicitní hodnoty, čímž se stanou nepovinnými.
# greet je argument s implicitní hodnotou
def hello(subj, greet="Hello"):
phrase = "%s %s!" % (greet, subj)
# return ukončí funkci a případně vrátí hodnotu
return phrase
# ponecháme implicitní hodnotu greet
print(hello("Prague"))
# použijeme greet jako keyword argument
# poziční argumenty musí být vždy jako první
print(hello("Praho", greet="Nazdar"))
# subj můžeme také použít jako keyword argument
print(hello(greet="Nazdar", subj="Praho"))
Hello Prague!
Nazdar Praho!
Nazdar Praho!
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.
Cvičení: Přepiště výpočet obsahu lichoběžníku do funkce
a = 3.5
b = 2.1
v = 77e-1
S = (a + b) * v / 2
print("Obsah lichoběžníku a=%g, b=%g, v=%g je: %g" % (a, b, v, S))
Obsah lichoběžníku a=3.5, b=2.1, v=7.7 je: 21.56
Z toho bychom rádi funkci - doplňte:
def trapezoid_area(...):
...
S = trapezoid_area(a, b, v)
Cell In[21], line 1
def trapezoid_area(...):
^
SyntaxError: invalid syntax
Vedlejší efekty u funkcí#
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.
def do_not_do_this(l):
# předpokládáme, že l je list
l.append("I'm here")
print("l inside the function")
print(l)
print("original list")
x = ["in my list"]
print(x)
do_not_do_this(x)
print("x after calling the function")
print(x)
# Toto už je lepší, neboť je zřejmé, že funkce vedlejší efekty má (a jaké asi jsou).
# Ale i tak by se to dalo vyřešit lépe.
def insert_item_into_list(l, item):
l.append(item)
original list
['in my list']
l inside the function
['in my list', "I'm here"]
x after calling the function
['in my list', "I'm here"]
Nemilé překvapení nás také může čekat, pokud implicitní hodnoty nějakého parametru jsou mutable.
def foo(l=[]):
# tady se mění l
l.append("appended")
print(l)
# zavoláme s explicitním argumentem
foo([])
# pak zavoláme s implicitní hodnotou - výsledek by měl být stejný
foo()
# zkusíme stejná dvě volání, očekáváme, že výsledky budou stále stejné, ale ...
foo([])
foo()
['appended']
['appended']
['appended']
['appended', 'appended']
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ř.
def foo(l=[]):
p = l + ["appended"]
print(p)
# zavoláme s explicitním argumentem
foo([])
# pak zavoláme s implicitní hodnotou - výsledek by měl být stejný
foo()
# zkusíme stejná dvě volání, výsledky už snad budou stejné
foo([])
foo()
['appended']
['appended']
['appended']
['appended']
5.9. Použití modulů#
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ů.
# Načte modul "math" a zpřístupní objekty v něm obsažené
import math
# cos je funkce definovaná v modulu "math"
print(math.cos(0))
1.0
Kromě importu modulů jako takových lze importovat i některé jejich části, v našem případě:
# Budeme s funkcí "cos" z modulu "math" zacházet, jako kdyby byla definována v aktuálním souboru
from math import cos
print(cos(0))
# Importuje všechny objekty, které v modulu najde. Obvykle se nedoporučuje používat, protože
# nevíme, co všechno modul obsahuje, a spousta pojmenovaných funkcí, tříd a proměnných by
# mohla kolidovat s něčím v aktuálním skriptu.
from math import *
1.0