Proměnné a typy dat
Tušíme, že počítače pracují nejen s čísly. A navíc, není číslo jako číslo.
[4]:
promenna1 = 10 # celé číslo
promenna2 = 10.0 # reálné číslo
promenna3 = 10.0+0.0j # komplexní číslo
promenna4 = '10' # řetězec
print(promenna1, promenna2, promenna3, promenna4)
10 10.0 (10+0j) 10
Ve výše uvedeném případě můžeme ze všech jedniček napsat dvojky, čímž se hodnoty všech čtyřech proměnných změní. To, co se ale nezmění, něco jako povaha těchto hodnot, je tzv. typ. Může se zdát, že jde o nedůležitou kategorii, a chápat ji jako jen jako přívažek hodnoty, nicméně při rozvažování o programu hraje typ důležitou roli.
V závislosti na typu proměnných označuje tentýž zápis velmi odlišné operace
1+2
bude3`
, protože do operace`+` vstupují čísla,'1'+'2'
bude'12'
, protože operandy "sčítání" jsou řetězce,\(\langle 1,2\rangle+\langle 10,20\rangle\) bude jednou \(\langle 11,22\rangle\) a jindy \(\langle 1,2,10,20\rangle\) podle typu, který symbolizují závorky \(\langle ... \rangle\).
Statické a dynamické typování
Jak se s takovou nejednoznačností může počítačový jazyk vyrovnat? Jsou dvě možnosti:
Jazyk používá statické typy takže ještě před spuštěním kódu, když narazí na identifikátor proměnné, může si být jistý, jaký typ dat v ní je uschován, a vytvořit kód plně využívající dovedností daného počítače. (Pokud jsou například sčítána celá čísla, vystačí s jedinou instrukcí mikroprocesoru). Sem patří jazyky jako FORTRAN a C.
Jazyk používá dynamické typy, kdy typ proměnné se zjišťuje až za běhu programu. Neexistuje pak pochopiteně žádná jedna instrukce procesoru, která by všechny možné stituace zvládla. To je příklad jazyka Python. (Námi používaný interpret CPython si místo instrukcí procesoru vytváří návod (pseudokód) jak, se zachovat ať bude typ dat jakýkoli, což zpomaluje výpočet. Jsou ale i další, pokročilejší varianty, které zpomalení zmenšují.)
Rychlost výpočtu, ilustrovaná výše zmínkou o počtu intrukcí potřebných k provedení operace +
není jedinou komplikací, kterou jazyk s dynamickými typy přináší.
Protože v Pythonu získá proměnná typ spolu hodnotou při exekuci přiřazovacího příkazu, musí při chápání významu operací s takovou proměnnou čtenář kódu více přemýšlet. např. pro kód p = a + b
na otázku, jaký typ dat obsahuje p
, nemůžeme odpovědět, aniž známe typ a
a b
. Na to nemusíme (nemůžeme) samozřejmě znát jejich konkrétní hodnotu, ale právě jen jejich typ. Právě ten rozhodne, co znamená +
. Z dobrého kódu by mělo být zřejmé, jakého typu ta která proměnná je.
Ještě uvidíme, že do hádání typu proměnných a výrazů se v moderních IDE pouší i editor kódu, který označuje nesprávné operace a napovídá, jaké operace jsou s daným typem možné.
Při psaní kódu bychom měli vědět, jakého typu proměnná je. Zjistit typ proměnné lze za běhu pomcí funkce type
a tedy kód
print(a)
print(type(a))
(v textové podobě ) vypíše nejprve hodnotu proměnné a
potom i její typ.
Čtyři proměnné, jejichž hodnotu jsme si již vypsali výše, mají následující typy (spojení <class x>
zatím překládejme jako "druh datové nádoby na uchovávání x"):
[5]:
print(type(promenna1), type(promenna2), type(promenna3), type(promenna4))
<class 'int'> <class 'float'> <class 'complex'> <class 'str'>
Vidíme zde následující typy proměnných/dat:
int
... celé číslofloat
... reálné číslocomplex
... komplexní číslostr
... řetězec
Klíčové je mít na paměti, že
Proměná: typ + hodnota
Proměnné vstupují (např.) do operací i se svým typem.
Typ proměnné určuje, jaký význam bude mít zapsaná operace a jakého typu bude výsledek
1 + 1 - 2
'1'+'1' - '11'
Hodnota proměnné pak určuje hodnotu výsledku operace.
Bez znalosti typu obou operandů nelze rozhodnout, zda je daná operace legální, např. a/b
dává smysl jen pro číselné typy. Python má velmi laxní statickou kontrolu kódu, takže taková chyba bývá často odhalena až při běhu programu. (Brzy se seznámíme s příklady nástrojů, které umožňují takovou chybu odhalit dříve.)
file "settings.json":
"python.analysis.typeCheckingMode": "basic"
Typ výsledku operace je dán typem operandů
Typ proměnných musíme brát v úvahu, když provádíme operace. Následující tabulka ukazuje, co se stane když použijeme operaci *
mezi různými typy. Povšimněte si, že kromě obvyklého chování čísel tu máme i množení řetězců, 'a'*4 - 'aaaa'
.
int
float
complex
str
int
int * int - int
int * float - float
int * complex - complex
int * str - str
float
float * int - float
float * float -
float float * complex - complex
float * str - Error
complex
complex * int - complex
complex * float - complex
complex * complex - complex
complex * str - Error
str
str * int - str
str * float - Error
str * complex - Error
str * str - Error
Binární operátory pro číselné výpočty
Zde je seznam nejčastějších binárních operátorů, jaké budeme používat symbol | význam --|---- + | součet - | rozdíl * | součin / | podíl ** | mocnění // | celá část podílu % | zbytek po dělení
Operace zbytku po dělení je definovaná i pro reálná čísla:
[4]:
import math
a = 314
b = a % (2*math.pi)
print(math.sin(a) , math.sin(b))
-0.15859290602857282 -0.15859290602856096
Všechny operace výše s výjimkou operace /
mají tu vlastnost, že výsledek je celé číslo, jen k když jsou oba opernady celé čísla
int * int - int
float * int - float
int * float - float
float * float - float
tedy
13//12 - 1
13//12.0 - 1.0
U dělení bylo v Pythonu od verze 3 upuštěno od této vlastnosti. Může totiž být snadnou příčinou chyb, protože zápis
energy = 1/2 * m * v * v
začíná výpočtem zlomku 1/2
, který má v čitateli i jmenovateli celé číslo. Pokud bychom (jak je tomu v C/C++) měli 1/2 == 0
, byla by za všech okolností takto spočtená kinetická energie nulová. V verzi Python 3 se tak můžete spolehnout, že 1/2 == 0.5
protože
int / int - float
Nebude ale na škodu, když budete takovéto zlomky psát preventivně např. jako 1.0/2
nebo 0.5
, kdyby si někdo váš kód vypůjčil do programu psaného v jiném jazyce.
Kontrolní otázky
Jak zjistíte typ dat obsažených v proměnné?
Jaké máme možnosti spočíst kolikrát se celé kladné číslo
x
vejde do jiného kladného čísla. Jak spočteme, kolik zbyde?Jakým výrazem spočteme, kolik vagónů (celé číslo) je potřeba k přepravě
m
tun materiálu, je-li nosnost každéhon
?