prev up next title end end

2. Hodnoty, výrazy a příkazy

  1. Hodnoty a typy objektů
  2. Typy datových objektů
  3. Booleovské hodnoty a výrazy
  4. Změna typu
  5. Proměnné
    1. Změna přiřazení
    2. Aktualizace proměnné
    3. Anotace proměnných
  6. Operátory a operandy
    1. Aritmetické operátory
    2. Bitwise operátory
    3. Operátory rozšířeného přiřazení
    4. Mroží operátor
    5. Relační operátory
    6. Logické operátory
    7. Speciální operátory
    8. Hvězdičkové operátory
    9. Pořadí operací
    10. Podtržítka
  7. Jména a klíčová slova
  8. Cvičení

Základní pojmy

Pro snazší chápání dalších výkladů je nutné osvětlit význam těchto dvou termínů:


2.1 Hodnoty a typy objektů

Ústředním pojmem objektově orientovaného (viz Kap. 10.1) programovacího jazyka Python je objekt - coby instance programové struktury, zvané třída.

Celou plejádu možných objektů lze zhruba rozdělit do dvou skupin:

  1. Na datové objekty, obsahující údaje (data), s nimiž lze pomocí jiných objektů pracovat - tyto objekty jsou blíže popsány v odstavci 2.2.
  2. Na provozní objety, schopné s uvedenými datovými objekty manipulovat - příkladem těchto objektů budiž funkce, metody a třídy (viz).

Každý objekt má jedinečnou hodnotu (value), typ (type) a identitu (ID).

Hodnota je inherentní význam datového objektu, vyjadřující množství (např. číslo), vlastnost (např. barvu) či jedinečnost (např. textový řetězec), s nímž může být v rámci výpočtu manipulováno. Každá hodnota je nositelem nějakého typu.

Typ je název třídy, z níž byl objekt odvozen. Typ objektu vymezuje množinu podporovaných operací a rovněž definuje možné hodnoty objektu. Pokud si nejsme jisti, k jakému typu neboli třídě objekt patří, zjistíme to vestavěnou (built-in) funkcí type():

>>> type("Hello, World!")    # Text v uvozovkách je objekt
<class 'str'>                  typu 'string' neboli řetězec
>>> type(17)                 # Celé číslo je objekt typu 'integer'    
<class 'int'>                              
>>> type(3.2)                # Desetinné číslo je objekt
<class 'float'>                    typu 'float'

Vězme tedy, že řetězce (strings) patří k typu str a celá čísla (integers) k typu int. Čísla s desetinnou čárkou (v Pythonu tečkou) patří k typu float. Přehled typů je uveden v následující části 2.2.

A což objekty jako "17" a "2.3"? Vypadají jako čísla, ale jsou v uvozovkách.

>>> type("17")
<class 'str'>
>>> type("2.3")
<class 'str'>

Jsou to řetězce. Řetězce mohou být v Pythonu uzavřeny v jednoduchých ('), dvojitých (") nebo i trojitých (''') uvozovkách. Uvnitř dvojitých uvozovek mohou být uvozovky jednoduché a obráceně: 'Pravil "Ne!" '.

Identita objektu je vyjádřena jeho identifikačním číslem (ID), které je adresou paměťového místa, ve kterém je aktuálně hodnota (v binární formě) uložena.
Některé objekty mohou mít explicitně přiřazené jméno, obecně označované jako proměnná. Typ proměnné je dán typem jí přiřazené hodnoty:

>>> num = 17; type(num), type(17)          # num je jméno proměnné           
(<class 'int'>, <class 'int'>)       
>>> id(num); id(17)        
(1835649200, 1835649200)                   # id(num) == id(17) --> True

Komentář na posledním řádku nutno brát s jistou rezervou, neboť ne vždy id(name) == id(value). Vždy však platí, že identita existujícího objektu je v rámci jedné seance neměnná.

Vznik objektu

Pro zvídavé

Není na škodu si uvědomit, že objekt (základní entita Pythonu) má tři stadia existence:

  1. jako entita, daná pravidly jazyka Python
  2. použitá možnost, daná deklarací objektu ve zdrojovém kódu (skriptu); toto stadium má dvě variety - objekty předdefinované (built-in), které jsou součástí programového vybavení Pythonu a objekty deklarované uživatelem ve skriptu
  3. realizovaná možnost, daná provedením zdrojového kódu interpretem

Nový objekt vzniká zpracováním programového textu interpretem Pythonu, přičemž je ověřováno, zda takový objekt již je či není v paměti počítače uložen.
Přiřazování identifikačních čísel k objektům je ve výlučné kompetenci Interpreta a do jisté míry se řídí řadou známých pravidel.

Opuštěná hodnota zůstává v paměti i po změně přiřazení. Z paměti zmizí až po ukončení aktuální seance Pythonu působením procedury garbage collection.


2.2 Typy datových objektů

Datové typy Pythonu slouží k ukládání různých druhů dat a k manipulaci s nimi.

Následující stručný přehled datových typů jazyka Python je zároveň přehledem jejich možných literálů (přímých zápisů jejich hodnoty). V přehledu jsou nejprve uváděny názvy typů, posléze jejich literály.

Speciální typy

Numerické typy (numbers)

Sekvence

Sekvence je uspořádaná a indexovatelná (subscriptable) množina hodnot, které nemění své pořadí:

Následující sekvenční typy pracují se sekvencemi bitů (viz 7.1):

Prvky všech sekvenčních typů jsou interně indexovány pořadovým číslem (indexem), počínajícím nulou (viz 3.1). To umožňuje přímý přístup k elementu sekvence.

U všech výše uvedených sekvenčních typů lze uplatnit tyto operace:
len(sekv), in sekv, seqv[i:j], min(sekv), max(sekv), sekv1+sekv2, sekv *number.

Kolekce

Částečně uspořádaná množina hodnot, která nepodporuje indexování - s výjimkou slovníku, který při výběru páru používá místo číselného indexu hodnotu jeho klíče (jímž může být i číslo).

Sekvence a kolekce jsou složené datové typy, sumárně označované jako kontejnery.
Specielním představitelem kontejneru je útvar, zvaný array, jenž je obdobou typu list, obsahující řadu hodnot stejného typu - viz Kap. 7.7.2.

Hodnoty specielních a numerických typů, jakož i typů tuple, range, string, bytes, frozenset, memoryview nelze dodatečně změnit; říkáme, že jsou neměnitelné (immutable).

Hodnoty typů list, set, dict, bytearray lze po jejich vytvoření dodatečně změnit; říkáme, že jsou měnitelné (mutable) - změna hodnoty nevyvolá změnu ID.

Python nemá datový typ pro jeden znak, v jiných jazycích označovaný termínem char . Nahrazuje jej řetězcem s jedním prvkem - např   "a".

Kromě uvedeného výčtu datových typů disponuje Python řadou dalších typů jako module, function, method, class, ... atd. Všechno v Pythonu je objekt a každý objekt je nějakého typu.

Počítání s čísly typu float

>>> f = 0.1 + 0.1 + 0.1; f           
0.30000000000000004

Podporu pro rychlé a správné zaokrouhlování při počítání s desetinnými čísly poskytuje modul decimal.

Modul decimal ošetřuje výpočty s desetinnými čísly tak, že vrací výsledek s nastavenou přesností:

>>> from decimal import Decimal

>>> x = Decimal('0.1')
>>> y = Decimal('0.1')
>>> z = Decimal('0.1')
>>> s = x + y + z; s; print(s) 
Decimal('0.3')
0.3

2.3  Booleovské hodnoty, funkce a výrazy

Pythonovský typ pro uložení hodnoty True nebo False zvaný bool je pojmenován po britském matematikovi George Booleovi, jenž vytvořil tak zvanou booleovu algebru, která je základem moderní počítačové aritmetiky.

>>> type(True); type(true)              # pouze True je OK!
<class 'bool'>
Traceback (most recent call last):
 NameError: name 'true' is not defined

Při porovnávání dvou objektů nutno rozlišovat mezi porovnáváním jejich hodnot nebo jejich identit; například dvě stokoruny mají stejné hodnoty ale nejsou to stejné objekty, majíce různá výrobní čísla.
V Pythonu je to obdobné, navíc lze porovnávat i typy objektů. Při porovnávání objektů používáme tuto zavedenou skladbu:

<levý operand> relační či specielní operátor <pravý operand>

Při porovnávání objektů používáme převážně operátory == a is, nikoliv operátor přiřazení:

>>> a = [1, 2, 3]; b = a; c = a[:]       # operátory přiřazení 
>>> c == b; c == a;
True True                # všechny objekty mají stejnou hodnotu
>>> c is b; c is a
False False              # pouze objekty 'a', 'b' jsou totožné
>>> print(id(a), id(b), id(c))
 2238680388544 2238680388544 2238674078912
>>> print(type(a), type(b), type(c), end=" ")
 <class 'list'> <class 'list'> <class 'list'>  

Vestavěná funkce bool() vrací booleovskou hodnotu čísel a řetězců. U číselných typů generují nulové hodnoty výstup False, nenulové hodnoty výstup True. Prázdné řetězce dávají False, neprázdné řetězce dávají True:

>>> bool(1)
True
>>> bool(0)
False
>>> bool("No!")                      # neprázdný řetězec
True
>>> bool("")                         # prázdný řetězec
False
>>> bool(3.14159)                    # nenulová hodnota
True
>>> bool(0.0)                        # nulová hodnota
False

2.4 Změna typu

Změna typu neboli konverze typu se provádí pomocí řady vestavěných funkcí.

Funkce str(value, base) přijímá objekty uvedených základních typů a přemění jej na objekt typu string.

>>> str(32), str(32.12), str(3+2j)      # deklarace entice
('32', '32.12', '3+2j')                 # entice (tuple) stringů

>>> str({3.6, "cat", True})             # konverze setu
"{True, 3.6, 'cat'}"

Funkce float() přijímá literály numerického typu int a přemění jej na typ float, například:

>>> float(12), float(0b10001), float(False)
(12.0, 17.0, 0.0)

Funkce int(value, base) přijímá literály a proměnné typu number (mimo complex), bytes a str a přemění jej na typ integer, například:

>>> int>(32.12), int(0b100000), int(True)
(32, 17, 1)

Pro převod celého čísla do jiného číselného formátu slouží funkce:

Funkce hex(integer) přijímá celé číslo a přemění jej na číslo se základem 16.

Funkce oct(integer) přijímá celé číslo a přemění jej na číslo se základem 8.

Funkce bin(integer) přijímá celé číslo a přemění jej na číslo se základem 2.

Všechny formáty celého čísla, vytvořené funkcemi hex(), oct(), bin(),   jsou typu integer:

>>> hex(32), oct(32), bin(32)
('0x20', '0o40', '0b100000')           # zobrazení jako string, ale:
type(0x20), type(0o40), type(0b100000)
(<class 'int'>, <class 'int'>, <class 'int'>)

Převod znaku na pořadové číslo systému Unicode provádí funkce ord() :

>>> ord(" "), ord("m"), ord("&")       # mezera je také znak
(32, 109, 38)

Převod pořadového čísla systému Unicode na příslušný znak provádí funkce chr() :

>>> chr(32), chr(109), chr(38)   
(' ', 'm', '&')

Pro převod sekvence (list, range, tuple, set, string, bytes) na sekvenci jiného typu slouží funkce list(), tuple(), set(), například:

>>> list("a5 True")                      # list z řetězce   
['a', '5', ' ', 'T', 'r', 'u', 'e']
>>> tuple("a5 True")                     # tuple z řetězce                     
('a', '5', '', 'T', 'r', 'u', 'e')
>>> set("a5 True")                       # set z řetězce
{'u', 'r', '', 'T', 'e', '5', 'a'}

Pro převod entice, seznamu či setu na slovník slouží funkce dict() - viz kap. 9.5.

>>> tup = (("a", 5), ("b", True))        # entice entic
>>> dit = dict(tup); dit                 # dict from tuple
{'a': 5, 'b': True}

>>> lup = [("a", 5), ("b", True)]        # seznam entic
>>> lip = dict(lup); lip                 # dict from list
{'a': 5, 'b': True}

>>> sup = {("a", 5), ("b", True)}        # set entic
>>> sip = dict(sup); sip                 # dict from set
{'a': 5, 'b': True}

Pro převod reálných čísel na číslo komplexní slouží funkce complex() :

>>> complex(3.2, 12)
(3.2+12j)

Funkce ascii(string) přijímá řetězec a vrací jej doplněný zpětnými lomítky u znaků, které nejsou obsaženy v kódování ASCii.

>>> ascii("žížala"), ascii("oves")
("'\\u017e\\xed\\u017eala'", "'oves'")

2.5  Proměnné

Proměnná (variable) nese uživatelské jméno, které odkazuje na přiřazený objekt, uložený pod identifikačním číslem (ID) v paměti počítače. Typ proměnné je dán typem přiřazeného objektu. Jméno bez přiřazeného objektu není akceptováno (ani mu není přiřazeno ID). Jména proměnných jsou case-sensitive, pomlčka uvnitř slova není povolena, jen podtržítko.

# Příklady názvů proměnných:
>>> a, a_a, A, aA,       

Podle zavedené konvence jsou jména, počínající velkým písmenen, vyhražena pro názvy tříd. Není doporučován ani formát "aA".

Objekt na pravé straně je ke jménu na levé straně připojujen operátorem přiřazení (=). Vše, co umístíme na pravou stranu operátoru přiřazení, musí Python znát nebo umět vytvořit:

>>> n = "hosana"                         # OK, objekt typu string
>>> pi = 3.14159                         # OK, objekt typu float
>>> x = ping                             # objekt není definován!
NameError: 'ping' is not defined
>>> ping = 5; type(ping)
 <class ´int´>                           # OK, objekt typu integer

Před vlastním přiřazením se vyhodnotí případný výraz na pravé straně.

>>> a = 5 + 3; a
8

Vazba jména na objekt se vyskytuje ve dvou místech:

  1. nejprve tam, kde je tato vazba deklarována, to jest v souboru (modulu) či v definici třídy nebo funkce
  2. poté je tato vazba zapsána do slovníku (jmenného registru) oblasti, příslušné místu deklarace

2.5.1  Změna přiřazení

Stejnému jménu lze postupně přiřazovat různé hodnoty (objekty):

>>> bruce = 5
>>> bruce
5
>>> bruce = 7; bruce
7

Nové přiřazení ruší přiřazení předchozí.

2.5.2  Aktualizace proměnné

Nejběžnější formou změny přiřazení je aktualizace, kdy nová hodnota proměnné závisí na její předchozí hodnotě, například:

>>> x = 6; id(x)                       # inicializace
 2161740743056
>>> x = x + 1; x; id(x)                # aktualizace
7
 2161740743088

Aktualizace proměnné přičtením hodnoty 1 se nazývá increment, aktualizace odečtením hodnoty 1 se nazývá decrement. Aktualizovaná proměnná musí mít předem přiřazenou počáteční hodnotu (viz inicializace).

Aktualizaci proměnné lze s výhodou provádět i pomocí operátorů rozšířeného přiřazení  +=  -=  *=  /=  //=  %=   (viz 2.6.3).

>>> y = 6
>>> y += 1; y    
7

2.5.3  Anotace proměnných

Anotace proměnných je označení předpokládaného typu (type hint) přiřazované hodnoty při deklaraci proměnné. Protože je Python dynamicky typovaný jazyk, je tato informace pro jeho interpreta zcela nezávazná. Slouží téměř výhradně k lepšímu chápání smyslu čteného skriptu uživatelem. Pomáhá při ladění kódu například pomocí aplikace mypy.
Náznakem typu lze opatřit deklaraci proměnné, parametry a vratnou hodnotu funkce, jakož i metody třídy.

Používaná skladba náznaků (hints):

Náznak typu proměnné:       name: type
Totéž s přiřazením hodnoty: name: type = value 

Náznaky u parametrů funkce: def func_name(a: type, b: type):
u výstupní hodnoty funkce:  def func_name(a: type, b: type): -> type:

Totéž platí pro metody, t.j. funkce, definované uvnitř třídy,
včetně iniciační metody __init__. 

Jako příklad si uveďme definici funkce, potvrzující pravdivost druhé věty úvodního odstavce:

# F:/Codetest/HowTopy/ch-02/annot_meth.py

def multi(a: int, b: int, x) -> str:  # náznaky typů včetně výstupu
    return (a + b) * x

print(multi(2.5, 7, 3))	              # --> 28.5
print(multi/('ha', 'ló ', 2))         # --> haló haló	

Interpret Pythonu náš předpis v pohodě ignoroval, protože ví, jak provádět součet a násobení a že tyto operace lze realizovat pro čísla i řetězce.
Pokud bychom tuto funkci realizovali pod dohledem aplikace mypy, dostalo by se nám v Terminálu těchto informací:

F:\Codetest\HowTopy\ch-02> mypy.exe annot_meth.py

annot_meth.py:5: error: Argument 1 to "multi"
 has incompatible type "str"; expected "int"  [arg-type]
annot_meth.py:5: error: Argument 2 to "multi"  has incompatible type "str"; 
expected "int"  [arg-type] 
annot_meth.py:6: error: Argument 1 to "multi"  has incompatible type "float"; expected "int"  [arg-type]
Found 3 errors in 1 file (checked 1 source file)

Předpoklad úspěšného provedení: Jsme "nacédovaní" do složky, obsahující zkoumaný skript a cestu k aplikaci mypy máme uloženou v proměnné PATH.


2.6 Operátory a operandy

Operátor je znak, zastupující funkci - prefixovou (stojící před operandem), infixovou (stojící mezi operandy) a postfixovou (stojící za operandem či funkcí - v Pythonu se nepoužívá).

Z hlediska použitých operandů rozeznáváme operace:

2.6.1   Aritmetické operátory

Aritmetickými operátory jsou znaky pro sčítání +, odčítání -, násobení *, umocňování **, dělení /, celočíselné dělení //, a operátor modulo % (dělení s celočíselným zbytkem).
Pořadí důležitosti (precedence) je následující: Závorky, Umocňování a odmocňování, Násobení a dělení, Sčítání a odčítání.

Operátor + lze kromě numerických hodnot použít také pro operandy typu str, list, tuple, bytes a bytearray, nikoliv však pro range, dict, set a frozenset:

>>> "naše" + " prasátko"                      
'naše prasátko'                               # string
>>> ["naše"]+["prasátko"]   
['naše', 'prasátko']                          # list
("naše",)+("prasátko",)
('naše', 'prasátko')                          # tuple
>>> b"our" + b" little pig"            
b'our little pig'                             # bytes
>>> bytearray(" naše", "utf-8") + bytearray(" prasátko", "utf-8")
bytearray(b' na\xc5\xa1e pras\xc3\xa1tko')    # bytearray 

Výše uvedené operandy lze rovněž násobit celým číslem. Objeví-li se na místě operandu proměnná, je kompilátorem zaměměna za svou hodnotu před tím, než se operace provede:

>>> hele, mese = "hele", "mese "
>>> (hele + mese)*3          # záporné číslo vrátí prázdný řetězec
'helemese helemese helemese '

Popsané součty operandů (kromě čísel) provádí Python při kompilaci v rámci zjednodušení (redukce) výrazů. U řetězců se tato procedura označuje jako zřetězení (concatenation).

Operátor celočíselného dělení // (floor division) zaokrouhluje kladný podíl směrem dolů. Pracuje i s desetinnými čísly.

>>> minute = 59 
>>> minute // 60  
0
>>> -minute // -60.0
0.0
>>> -minute // 60.0  
-1.0

Záporný podíl je zaokrouhlován směrem minus nekonečno k nejbližšímu celému číslu:

>>> -45/60, -1 < -0.75, -45 // 60.0, 
 (-0.75, True -1.0)

Operátor modulo pracuje s celými čísly (číselnými výrazy) a poskytuje zbytek při dělení prvního operandu druhým. V Pythonu jej označujeme znakem pro procento %. V pořadí operací má stejnou preferenci jako násobení.

>>> 7 % 3.0     
1.0

Ukazuje se, že modulo operátor je překvapivě užitečný. Na příklad, můžeme zjistit, zda jedno číslo je dělitelné druhým: je-li x % y == 0, pak x je dělitelné číslem y.

Lze jím také oddělit krajní číslice zprava od zadaného čísla. Například, x % 10 vyčlení nejkrajnější číslici čísla x zprava (při základu 10). Podobně x % 100 vyčlení dvě poslední číslice.

Použití operátoru modulo (%) si ukážeme v aplikaci Thonny na pěkném příkladu převodu vteřin na hodiny, minuty a zbývající vteřiny. Následující text si překopírujte jako skript do textového editoru Thonny a spusťte jeho provedení klikem na zelené ikoně:

# modulo.py

secs_celk = int(input("Kolik vteřin celkem?"))
hodiny = secs_celk // 3600
secs_navic = secs_celk % 3600
minuty = secs_navic // 60
sekundy = secs_navic % 60

print("Celkem vteřin: ", secs_celk)
print("Hodin, minut, vteřin: ", hodiny, minuty, sekundy) 

Výsledek pro zadaných 320 vteřin:

>>> %Run modulo.py
Kolik vteřin celkem? 320                 # vstup uživatele
Celkem vteřin:  320
Hodin, minut, vteřin:  0 5 20

2.6.2   Bitwise operátory

Bitwise operátory provádějí logické operace AND, OR, NOT, operaci XOR, jakož i operace levého a pravého posunu na binárních řetězcích, což jsou sekvence nul a jedniček.

Tyto operátory nejprve převedou celá čísla svých operandů do binárního formátu stejné délky, na tomto formátu provedou bit za bitem (bitwise) předepsanou operaci a výsledek posléze převedou zpět na celé číslo.
Příklady v následující tabulce jsou vyčísleny pro x,y = 12, 5 (0b1100, 0b0101):

Operátor Význam Příklad
   &    bitwise AND  1)   12 & 5    -->     4    (0b100)
   |   bitwise OR  2)   12 | 5     -->   13   (0b1101)
   ~    bitwise NOT 3)    ~12       -->  -13   (-0b1101)
   ^   bitwise XOR  4)   12 ^ 5    -->     9   (0b1001)
   <<    bitwise left shift  5)   12<< 2    -->   48  ('0b110000')
   >>    bitwise right shift   6) -12>> 2    -->    3  ('0b11')

Poznámka:
Operátor | se rovněž používá u množinové operace sjednocení (union).

Popisy operací:

  1. Vrací 1, jsou-li oba odpovídající bity = 1, jinak vrací 0.
  2. Vrací 1, je-li alespoň jeden z odpovídajících bitů = 1, jinak vrací 0.
  3. Vrací doplněk (komplement) čísla x k číslu 1: ~x = -(x+1)
  4. Vrací 1, je-li jeden z bitů = 1 a druhý = 0; jinak vrací 0.
  5. K binárnímu tvaru levé hodnoty přidá zprava nuly v počtu pravého čísla.
  6. Od binárního tvaru levé hodnoty odebere zprava numera v počtu pravého čísla.

Užitečné vztahy:

bin(~12)        --> '-0b1101'       # ~  --> bitwise NOT
bin(5^3)        --> ' 0b110'        # ^  --> bitwise XOR
int('110000',2) -->   48            # dtto int('0b110000',2)

Binární systém vyžaduje více paměťového prostoru než decimální systém ale je méně komplikovaný pro uplatnění v hardwaru počítače.

2.6.3   Operátory rozšířeného přiřazení

Rozšířené (augmented) přiřazení je kombinace binární operace (+, -, *, /, %, **, //) a příkazu přiřazení (=) v jednom výraze. Toto přiřazení provede změnu hodnoty existující proměnné, například pro x = 5 dostaneme:

 Operátor  x =    Příklad    Výstup pro x = 5:
     +=       5     x += 3     = 8
     -=       5     x -= 3     = 2
     *=       5     x *= 3      = 15
     /=       5     x /= 3     = 1.6666666666666667
     %=       5     x %= 3     = 2
     //=       5     x //= 3     = 1
     **=       5     x **= 3     = 125
     &=       5     x &= 3     = 1
     |=       5     x |= 3     = 7
     ^=       5     x ^= 3      = 6
     >>=       5     x >>= 3     = 0
     <<=       5     x <<= 3     = 40

2.6.4   Mroží operátor

Novějším (Python 3.8) způsobem přiřazení je přiřazení ve tvaru (var := val), označované jako přiřazení pojmenovaného výrazu nebo pojmenovaný výraz. Pro zavedený operátor (:=) se ujalo označení mroží operátor (walrus opreator).
Tento operátor umožňuje provést okamžitě použitelné přiřazení uvnitř výrazu (expression).

(variable := expression)       # závorky jsou povinné
Prostý příkaz přiřazení nevrací hodnotu:
>>> mrož = "walrus"; u = 5 + 3*2
>>>
Mrožík má rád kulaté závorky, bez závorek produkuje Syntax Error.
Přiřazení s výrazem vrací hodnotu:
>>> (mrož := "walrus"); (u := 5 + 3*2) 'valrus' 11 >>>

2.6.5   Relační operátory

Relační operátory vyjadřují tvrzení o kvantitativním vztahu mezi dvěma hodnotami. Jsou to tyto operátory:

    x == y                        # x je rovno y
    x != y                        # x není rovno y
    x >  y                        # x je větší než y
    x <  y                        # x je menší než y
    x >= y                        # x je větší nebo rovno y
    x <= y                        # x je menší nebo rovno y

Jednotlivé tvrzení (statement) může být buď pravdivé nebo nepravdivé.

>>> 5 < 3
>>> False
>>> 5/3 < 10
>>> True

Rovnítko (=) není operátorem, nýbrž znakem pro přiřazení hodnoty ke jménu. Tato veledůležitá vázací operace (binding) umožňuje pracovat s objekty prostřednictvím jejich jmen.

Je nutné rozlišovat mezi pojmem rovnost (equality ==) a totožnost (identity is):

>>> x, y = [1, 2, 3], [1, 2, 3]    # přiřazení hodnot k proměnnym
>>> id(x), id(y)
 (2536047102656, 2536006818688)
>>> x == y; x is y                 # --> True, False - není totožné

2.6.6   Logické operátory

Logické (booleovské) operátory provádějí některé logické operace se zadanými operandy. Tyto operátory jsou tři: and , or a not. Jak vidíme, jsou to zároveň klíčová slova. Význam těchto operátorů je podobný jejich významu v češtině (a, nebo, ne).
Například, výrazy x > 0 AND x < 10 jsou pravdivé podle pravidel formální logiky pouze tehdy, jsou-li pravdivá obě tvrzení, to jest, je-li x větší než 0 a zároveň menší než 10.

Tvrzení n%2 == 0 OR n%3 == 0 je pravdivé, je-li alespoň jedna z podmínek pravdivá, to jest, je-li číslo dělitelné dvěma nebo třemi.

Konečně, operátor not neguje následující booleovský výraz, takže not(x > y) je pravda, je-li x > y nepravda; to jest je-li x menší nebo rovno y.

2.6.7   Speciální operátory

Operátory totožnosti (identity) - is a is not ověřují, zda dva objekty mají stejné ID i stejnou hodnotu:

>>> x1 = y1 = 5                # přiřazení hodnoty k proměnnym
>>> x2 = y2 = "hej"            # dtto
>>> x1 is not y1               # False  - operandy jsou identické
>>> x2 is y2                   # True   - id(x1) == id(y1)

Operátory příslušnosti (membership) in a not in ověřují, zda je zkoumaná proměnná přítomna v zadané sekvenci (string, list, tuple, set a dictionary):

>>> x = "Nazdárek!"               # string (řetězec)
>>> y = {1:"a", 2:"b"}            # dictionary (slovník)

>>> 'H' not in x                  # True
>>> 1 in y                        # True

2.6.8   Hvězdičkové operátory

S hvězdičkami se nám v Pythonu roztrhl pytel. K původním aritmetickým operátorům pro násobení (*) a umocňování (**) máme aktuálně ještě:

  1. hvězdičky jako regulační znaky ve výčtu parametrů funkce; samotná hvězdička přikazuje aby všechny následující parametry přijímaly pouze párové argumenty funkce; doplňkem k hvězdičce ve výčtu parametrů je lomítko ve výčtu parametrů, které nařizuje aby všechny předcházející parametry přijímaly pouze poziční argumenty funkce -viz Kap. 4.2.2
  2. hvězdičky jako dekorátory variadických parametrů či argumentů *args pro sekvence a **kwargs pro slovníky - viz Kap.4.2.3 a 4.2.4

2.6.9 Pořadí operací

Objeví-li se ve výrazu více než jeden operátor, závisí pořadí výpočtu na pravidlech o pořadí operací. Python (až na výjimky) respektuje stejná pravidla, jaká se používají v matematice.

Operátor Název, použití
  ()   závorky
  a**n,  a**(1/n)   umocnění, odmocnění
  +x, -x,   ~x     unární +, - ,   bitwise NOT
  *,  /,  //,  %    násobení, dělení, celočís. dělení, operátor modulo
  +, -   aritmetický součin, podíl
  <<, >>   bitwise left shift, bitw. right shift
  &, ^, |   bitwise AND, XOR, OR - dle pořadí
  <, <=, >, > =;  ==, !=   relace;  rovná se, nerovná se
  (+ - * / ** // %) =   složené přiřazení (+=, *=, ...)
  not, and, or   logické operátory - dle pořadí
  is, is not   operátory identity
  in, not in   operátory příslušnosti
  :=   'mroží' operátor

Téměř všechny operátory se stejnou prioritou jsou vyhodnocovány zleva doprava (jsou asociativní zleva).

>>> 7 * 3 // 2          # (7 * 3) // 2
10

Opakované mocniny jsou vyhodnocovány zprava doleva (jsou asociativní zprava).

 2**3**2                # 2**(3**2)  
512
>>> 7*8**(1/3)          # 7 * 8**(1/3)
14.0

Některé operátory nemají asociativitu a řídí se jinými pravidly, například:

x < y < z     -->  x < y and y < z

2.6.10 Podtržítka

Podtržítka mají různý význam v různých situacích.

  1. Lze je použít jako oddělovač skupiny čísel:

    >>> mils = 1_200_000    
     1200000
    

    Obdobně lze oddělovat části binárního, oktálního a hexadecimálního čísla: 0b_10001, 0o_21, 0x_11.

  2. V konzole interpreta představují poslední uloženou hodnotu výrazu:
    >>> 2 + 3
     5
    >>> _ * 3
     15
    
  3. Vyjadřují anonymní hodnotu:
    >>> for _ in range(6):
           print(_*_, end=" ")       # 2x anonym. hodnota
     0 1 4 9 16 25
    
  4. Podtržítko místo jména proměnné způsobí nepoužití odpovídající pozice ve výčtu přiřazovaných hodnot:
    # Ignorována jedna hodnota:
    >>> a, _, b = (1, 2, 3)
    >>> print(a,",", b)                    # --> 1 , 3
    
    # Ignorováno více hodnot:
    >>> c, *_, d = 1, 2, 3, 4, 5
    >>> print(c,",", d)                    # --> 1 , 5
    
  5. Jednoduché podtržítko jako přípona slouží k rozlišení aktuálně deklarovaného jména od stejnojmenného klíčového slova:
    >>> def pattern(name, class):    # class je klíčové slovo
            pass
    SyntaxError: "invalid syntax"  
    
    >>> def pattern(name, class_):   # OK
            pass                              
    
  6. Jednoduché podtržítko jako předpona jména vyjadřuje pouze upozornění, že deklarovaná třída, metoda, funkce nebo modul je zamýšlen pro interní použití uvnitř aktuálního modulu, třídy nebo paketu. Externímu použití však bráněno není:
    >>> class myClass:
            def __init__(self):
                self._bar = "Aleluja!"
    
    >>> myc = myClass(); myc._bar
    'Aleluja!'		
    
  7. Dvojité podtržítko před jménem atributu třídy je signál pro kompilátor aby v interním seznamu __dir__ připojil název třídy k názvu atributu (viz dir(obj)), čímž zamlží jeho existenci. Popsaný proces se označuje jako komolení názvu (name mangling):
    class myClass:
       def __init__(self):
          self.__x = 20           # privátní název atributu
       def __myFunc(self):        # privátní název atributu
          print("Hello, World!")     
     
    obj=myClass()                 # instance třídy
    

    Názvy s předsazenými dvojitými podtržítky jsou externě nepřístupné:

    >>> obj.__x
    NameError: name 'obj' is not defined
    

    Zkomolené (mangled) názvy atributů __x__myFunc() mají tvar :   _myClass__x, _myClass__myFunc(). Pouze v této formě jsou externě přístupné:

    >>> obj._myClass__x; obj._myClass__myFunc()
    20
    Hello, World!
    
  8. Dvojitá podtržítka před i za názvem (double underscores - dunders) metody označují speciální metodu třídy - viz kapitola 10.9.


2.7 Jména a klíčová slova

Jména (identifiers) proměnných, jakož i funkcí a tříd, mohou být libovolně dlouhá. Mohou obsahovat jak písmena tak číslice, ale musejí začínat písmenem a nesmějí obsahovat mezeru. I když je přípustné použít velká písmena, z konvenčních důvodů to neděláme. Pokud tak učiníme, musíme si uvědomit, že velikost písmena hraje roli. Bruce a bruce jsou různá jména.

Podtržítko _ se ve jménu smí použít (naopak pomlčka - se používat nemá). Často se používá u jmen s více slovy, jako je moje_jmeno nebo price_of_tea_in_china. Podtržítko na počátku názvu mívá speciální význam, takže jej zatím raději takto nepoužívejme.

Dáme-li proměnné nepřípustné jméno, obdržíme syntaktickou chybu:

>>> 76trombones = "big parade"
SyntaxError: invalid syntax
>>> more$ = 1000000
SyntaxError: invalid syntax
>>> class = "Computer Science 101"
SyntaxError: invalid syntax

76trombones není legální, protože nezačíná písmenem, more$ není legální, protože obsahuje nedovolený znak, označení dolaru. Co je ale špatného na class ?

Ukazuje se, že class je jedno z klíčových slov Pythonu. Klíčová slova jsou vyhrazená slova a nemohou být použita jako jména proměnných.

Python má aktuálně třicet dva plus tři klíčová slova:

   and     as        assert  async    await     break    
   class   continue  def     del      elif      else     
   except  finally   for     from     global    if
   import  in        is      lambda   nonlocal  not
   or      pass      raise   return   try       while   
   with    yield     True    False    None

Aktuálně platný seznam klíčových slov získáme zadáním příkazu:

>>> help("keywords")

Informaci o klíčovém slově získáme zadáním příkazu (například "raise"):

>>> help("reise")

Význam jednotlivých klíčových slov je (anglicky) uveden zde

Kromě výše uvedených klíčových slov existují 4 tak zvaná měkká klíčová slova (soft keywords): match, case, type a _ (podtržítko).


2.8  Cvičení

  1. Co se stane, když dáte příkaz k tisku přiřazení?
    >>> print(n = 7)
    
    A což toto?
    >>> print(7 + 5)
    
    Nebo toto?
    >>> print(5.2, "toto", 4-2, 5/2.0)
    
  2. Následující číselné výrazy vypočítejte z hlavy a výsledky si následně ověřte v konzole:
    >>>  5 % 2
    >>>  9 % 5
    >>>  15 % 12
    >>>  12 % 15
    >>>  6 % 6
    >>>  0 % 7
    >>>  7 % 0
    
  3. Přidejte závorky k výrazu 6 * 1 - 2 tak, aby se změnila jeho hodnota ze 4 na -6.
  4. Za prompt v konzole Pythonu zapište houby + 4. To vyvolá chybu:
    NameError: name 'houby' is not defined
    
    Jménu houby přiřaďte takovou hodnotu, aby houby + 4 bylo 10.
  5. Dovedl byste zapsat následující vzorec pro výpočet výsledné hodnoty A počátečního vkladu P jako sled výrazů (nikoliv jako funkci) v programovém jazyce Python?
    kde:
    • P = počáteční vklad
    • r = úroková míra per annum jako desetinné číslo
    • n = počet hodnocených období za rok
    • t = počet roků
    Pro P=10000 Kč, n=12 měsíců, r=8%(0,08) a t=10 let by hodnota A měla být přibližně 22.196,4 Kč.

    Úlohu řešte v interaktivním i programovém režimu v aplikaci IDLE. Skript vložte do souboru vynos.py ve složce kap-02.

  6. Každé slovo věty All work and no play makes Jack a dull boy připojte hromadným přiřazením k vlastní proměnné a potom větu vytiskněte na jeden řádek s použitím funkce print().

prev up next title end end