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.

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:

In [1]:
# - 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)."""
Out[1]:
'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).'

Jednoduché příkazy

Zkuste si následující příkazy a nějaké jejich obměny.

In [2]:
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'>
Out[2]:
1.55
In [3]:
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
In [4]:
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
In [5]:
from math import sin, pi    # import pouze některých položek
a = sin(pi / 4)
print('a = %.3g' % a)
a = 0.707
In [6]:
a = cos(pi / 2)             # tohle asi nebude fungovat --> výjimka
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-6-234a56bb45c2> in <module>()
----> 1 a = cos(pi / 2)             # tohle asi nebude fungovat --> výjimka

NameError: name 'cos' is not defined

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 kontextu
  • eval -- 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í souboru
  • print -- výpis řetězce do stream
  • raw_input -- načtení vstupu od uživatele (stdin)
  • str, repr -- text reprezentující daný objekt
  • type -- vrátí typ argumentu

Blíže se s těmito a dalšími vestavěnými funkcemi se seznámíme brzy.

In [7]:
print(str(dir()) + "\n")
print(repr(dir("a")))
['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']

['__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']
In [9]:
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
a * 4 = 8, a = 2

Přehled operátorů v Pythonu

+       -       *       @       **      /       //      %
<<      >>      &       |       ^       ~
<       >       <=      >=      ==      !=      <>
or      and     not
is      is not  in      not in

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

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.

In [10]:
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).

In [11]:
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í:

In [12]:
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.

In [13]:
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.

In [14]:
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
In [15]:
# 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

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.

In [16]:
dlouhy_nazev_promenne = "pomoci plus vytvorime pro ukazku nejaky dlouhy retezec znaku, " + \
                        "ktery nedava zadny velky smysl ..."
dlouhy_nazev_promenne
Out[16]:
'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é.

In [17]:
dlouhy_nazev_promenne = (10000000000000 + 2222222222222222 + 9999999999999999 + 3987493874 +
                         444444444444444 + 23987342978 + 9874 + 555555555555555555 +
                         987349987 - 9999999999999999999)
dlouhy_nazev_promenne
Out[17]:
-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í.

Definice funkcí

Základem pro definici funkcí je klíčové slovo def. Opět to ukážeme na příkladech.

In [18]:
# 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.

In [19]:
# 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.

In [20]:
# 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

In [21]:
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:

In [ ]:
def trapezoid_area(...): 
    ...
    
S = trapezoid_area(a, b, v)

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.

In [22]:
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.

In [23]:
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ř.

In [24]:
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']

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ů.

In [25]:
# 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ě:

In [26]:
# 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

Komentáře

Comments powered by Disqus