![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Elementy sekvencí a kolekcí jsou interně indexovány a pomocí těchto indexů jsou přímo dostupné závorkovým operátorem
Názornou ilustraci indexování těchto elementů představuje obrázek:
Indexování zleva začíná nulou, indexování zprava doleva se provádní pomocí záporných čísel.:
>>> pozdrav = "Hello World" >>> pozdrav[5] ' ' >>> pozdrav[-5] 'W' >>> pozdrav[11]IndexError: string index out of range >>> pozdrav.__getitem__(0) 'H'
Hodnoty elementů objektu typu
>>> dc = {"m": 5, "n": 6}# objekt s klíči "m", "n" >>> dc["m"]# použití závorkového operátoru 5 >>> dc.__getitem__("n")# použití metody 6 >>> for i in dc:# použití indexu ve smyčce print(dc[i], end =" ") 5 6
Iterace
je opakovaný výpočet pro hodnoty jednotlivých členů
Iterovatelným objektem (iteráblem) jsou sekvence typu
Iterace iteráblu produkuje 'dychtivý' (eager) výstup, iterace iterátoru produkuje 'líný' (lazy) výstup, viz odst. 3.6.3.
Iterábl
je
Iterátor
je interní objekt, vytvořený pro iterábl explicitně funkcí
Implicitně si iterátor ze zadaného iteráblu vytváří smyčka
Iterátory jsou výhodné tím, že snižují spotřebu paměti; vyprázdněný iterátor je "garbage collected".
Iterátor lze generovat i generátorovou funkcí a generátorovým výrazem - viz odst. 3.6.
Iterátory, definované třídou, jsou popsány v kap. 13.5.
Funkce
>>> li = [2, 5, 0]# iterable >>> ili = iter(li)# vytvoření iterátoru >>> ili = li.__iter__() # alternativní způsob >>> next(ili)# první krok iterace 2 >>> ili.__next__()# alternativně další krok iterace 5 >>> next(ili)# poslední krok iterace 0 >>> next(ili)StopIteration # info o konci iterace
Iterátor je v této chvíli prázdný. Opětovně použitelný iterátor vytvoříme opětovným použitím funkce
To platí i při aplikaci smyčky
>>> ili = iter(li) >>> next(ili) 2 >>> for i in ili: print(i, end =" ") 5 0 >>> next(ili)StopIteration Nutno poznamenat, že při aplikaci smyčky for .. pro iterábl li žádné " >>> for i in li: print(i, end =" ") 250StopIteration " nehrozí, neboť si smyčka vytvoří svůj vlastní interní iterátor:
Hromadné přiřazení (multiple assignment, tuple- or iterable unpacking) umožňuje přiřadit jediným příkazem výčet hodnot na pravé straně k výčtu jmen na straně levé. Výčet jmen na levé straně má formát entice (tuple) nebo seznamu (list). Tento příkaz lze zadat dvojím způsobem:
# V jednom řádku: >>> x,y,z = 10,20,30; x,z (10, 30)# Ve dvou řádcích: >>> seq = 1,2,3 >>> a,b,c = seq; a,c (1, 3)# Entici (tuple) bez závorek akceptuje interpret jako entici se závorkami.
Při stejném počtu prvků na obou stranách proběhne jejich propojení v zadaném pořadí.
Výčet hodnot na pravé straně může mít formát entice (tuple), seznamu (list), řetězce (string), setu (set), slovníku (dictionary) a rozsahu (range).
>>> a,b = [12, 22]; a,b# tuple = list (12, 22) >>> c,d,e = "Haf"; c,d,e# tuple = string ('H', 'a', 'f') >>> f,g = {5, "pivo", 5}; f,g# tuple = set ('pivo', 5) >>> f,g = {"j":15, "k":25}; f,g# tuple = dict ('j', 'k')(vrací jen klíče) >>> b,f,l = range(3); b,f,l# tuple = range (0, 1, 2)
Hromadným přiřazením rozbalíme slovník ve smyčce for ...
>>> dic = {'a':2, 'b':4, 'c':10} >>> for pol in dic.items() :# vestavěná methoda key, value = pol# hromadné přiřazení print(f"Klíč {key} má hodnotu {value}") Klíč a má hodnotu 2 Klíč b má hodnotu 4 Klíč c má hodnotu 10
Hromadné přiřazení lze výhodně použít i ve spojení s funkcí, pokud její invokace produkuje stejný počet hodnot jako zadaný počet proměnných:
>>> def mocniny(num): return num, num**2, num**3 >>> num, sqr, cub = mocniny(2)# hromadné přiřazení >>> num, sqr, cub# invokace (2, 4, 8)
Hromadné přiřazení použijeme i ve spojení s komprehencí iteráblu (viz 3.5):
>>> x,y,z = (x**2 for x in (1,3,5))# hromadné přiřazení >>> x,y,z# invokace (1, 9, 25)
Hromadným přiřazením lze rozbalit i vnořené iterábly:
>>> body = (1,2), (-1,-2)# entice entic >>> (x1,y1), (x2,y2) = body# hromadné přiřazení >>> print(f"x1,y1 ={x1,y1}, x2,y2 ={x2,y2}") x1,y1 =(1, 2), x2,y2 =(-1, -2)
Hromadné přířazení použijeme výhodně při záměně přiřazení:
>>> x,y,z = 10,20,30 >>> z,y,x = x,y,z >>> x,y,z (30, 20, 10)
Alternativní označení hromadného přiřazení je
Pokud je
>>> *a, = 1,2,3,4,5; a# *a, je entice (tuple) [1,2,3,4,5]# tuple balí do listu >>> [*a] = 1,2,3,4,5; a [1,2,3,4,5]# stejně jako list
Ve výčtu jmen na levé straně smí být jen jedna hvězdičková proměnná. Neohvězdičkovaná jména se nazývají
>>> a,*b,c = 1,2,3,4,5; a,b,c (1,[2,3,4],5) >>> a,*_,c = 1,2,3,4,5; a,_,c# _ je 'anonymní' proměnná (1,[2,3,4],5) >>> a,*b,c = 1,2; a,b,c# OK: 3 <= 1 + 2 (1,[],2)
Možné jsou i tyto (poněkud rozpustilé) kombinace:
>>> f,*m,(*ir,il) = 0,1,2,3,(4,5,6)# přiřazení >>> f; m; ir; il# invokace 0 [1, 2, 3] [4, 5] 6
Hvězdičkové operátory jsou mnohdy nezbytné pro rozbalení některých iteráblů:
>>> *ran, = range(8); ran# tuple či list na levé straně! [0, 1, 2, 3, 4, 5, 6, 7] >>> r = list(ran); r# alternativní invokace [0, 1, 2, 3, 4, 5, 6, 7] >>> *gen, = [2**x for x in range(8)]; gen# komprehence [1, 2, 4, 8, 16, 32, 64, 128]
Hromadné přiřazení s hvězdičkovým členem usnadňuje přístup k prvkům iteráblu bez použití indexů:
>>> items = "zdař", 25, True, 2+5Výběr pomocí indexů: >>> print(f"První položka je {items[0]}, poslední je {items[-1]}") První položka je zdař, poslední je 7Výběr hromadným přiřazením: >>> first, *middle, last = items >>> print(f"První položka je {first}, poslední je {last}") První položka je zdař, poslední je 7
Dekorace **, uvedená před názvem slovníku, přikazuje jeho rozbalení před dalším použitím:
>>> dic = {'a':2, 'b':4, 'c':10} >>> def fun(a,b,c): return a,b,c >>> fun(**dic) (2, 4, 10)
Jiný příklad se sloučením slovníků:
>>> prvý = {"A": 1, "B": 2} >>> druhý = {"C": 3, "D": 4} >>> spolu = {**prvý,**druhý,**{"e": 5, "f": 6}}# deklarace >>> spolu# invokace {'A': 1, 'B': 2, 'C': 3, 'D': 4, 'e': 5, 'f': 6}
Jen tak mimochodem - stejně úsporně lze totéž provést operátorem | (Python 3.9):
>>> prvý = {"A": 1, "B": 2} >>> druhý = {"C": 3, "D": 4} >>> spolu = prvý | druhý | {"e": 5, "f": 6} >>> spolu {'A': 1, 'B': 2, 'C': 3, 'D': 4, 'e': 5, 'f': 6}
Smyčky jsou často užívány v programech, které spočítají výsledek tak, že začnou s přibližnou hodnotou a opakovaným výpočtem výsledek zpřesňují.
Například, jedním ze způsobů počítání druhé odmocniny čísla je Newtonova metoda. Při určení odmocniny čísla
beclr-tter = (approx + n/approx)/2
Výpočet se opakuje tak dlouho, až se zpřesněná hodnota téměř neliší od předchozí. Pro provádění výpočtu napíšeme funkci:
def sqrt (n): approx = n/2.0 better = (approx + n/approx)/2.0while better != approx: approx = better better = (approx + n/approx)/2.0return approx
Volejme funkci pro argument 25, abychom se přesvědčili, že výsledek je 5.0.
Newtonova metoda je příkladem algoritmu - obecného řešení určitého problému (v našem případě počítání druhé odmocniny).
Komprehence je skladebný předpis pro vytvoření
Komprehenci ad b) lze ilustrovat matematickým výrazem, který pro všechna
S = { 2*x | x € N, x² > 3 }
Obdobou výše uvedeného matematického výrazu může být toto schéma skladby v Pythonu:
S =[ f(x) for x in <objekt> if <podmínka>]
Vedlejším produktem idiomu
Ukažme si konkretní příklad (prozatím bez podmínky) komprehence
>>>li, tu, st = [1, 2, 3, 4], (1, 2, 3, 4), {1, 2, 3, 4} >>> cli=[x**2 for x in li]; cli [1, 4, 9, 16]#1 list z li >>> cli={x**2 for x in li}; cli {16, 1, 4, 9}#1 set z li cli=(x**2 for x in li); cli#<generator object <genexpr> at 0x0000020A9AED5630> >>> cli=tuple (x**2 for x in li); cli (1, 4, 9,16)#1 tuple z li >>> ctu=[x**2 for x in tu]; ctu [1, 4, 9, 16]#2 list z tu >>> ctu={x**2 for x in li}; ctu {16, 1, 4, 9}#2 set z tu >>> ctu=(x**2 for x in tu); ctu#<generator object <genexpr> at 0x0000020A9AED5630> >>> ctu=tuple (x**2 for x in tu); ctu (1, 4, 9, 16)#2 tuple z tu cst=[x**2 for x in st]; cst [1, 4, 9, 16]#3 list z st cst={x**2 for x in st}; cst {16, 1, 4, 9}#3 set z st cst=(x**2 for x in st); cst<generator object <genexpr> at 0x000001DA317B5AF0> cst=tuple (x**2 for x in st); cst (1, 4, 9, 16)#3 tuple z st
Jak uvedeno, komprehovat lze iterábly
Komprehence pro
Dále si ukážeme komprehenci s podmínkou:
>>> numbers = [1, 3, 2, 5, 3, 1, 4] >>> {x**2 for x inVýrazových předpisů může být v jedné komprehenci více:numbers if x**2 > 3} {16, 9, 4, 25}# komprehence s podmínkou a redukcí >>> >>> files = ('bin', 'Data', 'Desktop', '.bashrc', '.ssh', '.vimrc') >>> [name for name in files if name[0] != '.'] ['bin', 'Data', 'Desktop']# komprehence s podmínkou
>>> [(x, x**2, x**3) for x inMůže být více i poskytnutých objektů:numbers ]# komprehence seznamu [(1, 1, 1), (2, 4, 8), (3, 9, 27), (4, 16, 64)]
>>> numbers = (1, 2, 3, 4) >>> letters = ['a', 'b', 'c'] >>> [n*letter for n in numbers for letter in letters] ['a', 'b', 'c', 'aa', 'clr-bb', 'cc', 'aaa', 'clr-bbb', 'ccc', 'aaaa', 'clr-bbclr-bb', 'cccc']
Zajímavá je úprava argumentu v této komprehenci:
>>> [v*2 for v in ("a", 5, True)] ['aa', 10, 2]# 2*True = 2*1 = 2
Za povšimnutí stojí i toto spojení komprehence s formátováním řetězce dle kap. 6.11:
>>> chlapci = ["Pavel", "Petr", "Jan"] >>> synci = ["{} Novotný".format(boy) for boy in chlapci] >>> synci ['Pavel Novotný', 'Petr Novotný', 'Jan Novotný']
Ukázka komprehence setu z řetězce:
>>> s = {v for v in "ABCDABCD" if v not in "CB"}; s {'A', 'D'}
Komprehencí setu z řetězce lze s pomocí funkce
>>> d = {key:val for key,val in enumerate ('ABCD') if val not in "CB"} >>> d {0: 'A', 3: 'D'}
Zajímavé je použití pojmenovaného výrazu (mroží operátor - 2.6.6) při komprehenci seznamu:
>>> def f(x): return x + 2 >>> print([(y := f(x), x/y) for x in range(3)]) [[2, 0.0], [3, 0.3333333333333333], [4, 0.5]]případně se zaokrouhlením des. čísla dle kap. 6.13: >>> print([[y := f(x), round(x/y, 2)] for x in range(3)]) [[2, 0.0], [3, 0.33], [4, 0.5]]případně s podmínkou a přehledněji: >>> print([(x, y, round(x/y, 2)) for x in range(3) if (y := f(x)) > 0]) [(0, 2, 0.0), (1, 3, 0.33), (2, 4, 0.5)]
Následující komprehencí vybereme ze zadané množiny bodů ty, které leží uvnitř kružnice o poloměru r = 2:
>>> import math >>> radius = 2 >>> [(x, y) for x in range(-2,3) for y in range(-2,3) if ... math.sqrt(x**2 + y**2) < radius] [(-1,-1), (-1,0), (-1,1), (0,-1), (0,0), (0,1), (1,-1), (1,0), (1,1)]
Generátor je 'líný' iterátor, který místo vytváření hotových objektů ukládá instrukce pro jejich individuální použití při vlastní iteraci. Je to
Generátorový výraz vytváří
>>> st = "abakus"# iterovatelný řetězec - iteráble >>> stv =(i for i in st) # interní objekt - iterátor >>> for i instv : print (i,end=" ")# líná (lazy) iterace iterátoru a b a k u s >>> for i inst : print (i,end=" ")# normální, dychtivá (eager) iterace iteráblu a b a k u s
Generátorový výraz lze vytvořit i s použitím idiomu
>>> gv = (i*i for i in range(5))# interní objekt - iterátor >>> for i in gv: print (i, end=", ")# líná (lazy) iterace 0, 1, 4, 9, 16
Generátorová funkce je normální funkce, která místo příkazu
def count_to(m) :# vrací iterátor n = 0while n <= m:yield n # poskytuje elementy iterátoru n += 1
>>> ct = count_to(5)# gener. objekt, iterátor # Invokace iterátoru: >>> next(ct)# 1. krok iterace (funkce) 0 >>> ct.__next__()# 2. krok iterace (metoda) 1 >>>for i in ct: print (i, en" ")# opakovaná iterace 2 3 4 5smyčkou for ... >>> next(ct)StopIteration # iterátor je prázdný >>> ct = count_to(5)# objekt nutno obnovit >>> print(list(ct)) [0, 1, 2, 3, 4, 5]# výtisk generátor. objektu >>> print(list(ct)) []# iterátor je prázdný
Generátorový objekt (iterátor) vytvoří i tato generátorová funkce:
def squares (start, stop):for iin range (start, stop):yield i * i
>>> sq = squares(1,7)# lazy iterátor print(list(sq)) 1 4 9 16 25 36# výtisk generátor. objektu >>> for i in sq:# opakovaná iterace print (i, end=" ")smyčkou for ... 1 4 9 16 25 36
Výpočet řady Fibonacciho čísel můžeme provést pomocí následující generátorové funkce s nekonečnou smyčkou (!):
def fibonacci ():# generátor. funkce > a, b = 0, 1while True:# nekonečná smyčka yield a a, b = b, a+b
Generátorový objekt (iterátor) s nekonečnou smyčkou voláme pro konkretní mez funkce
>> f = fibonacci()# generátor. objekt, iterátor >> type(f)# --> <class 'generator'> >> f.__next__()# --> 0 >> next(f)# --> 1 alternativní verze >> next(f)# --> 1 >> for i in range(7): print(next(f), end=", ") 2, 3, 5, 8, 13, 21, 34, >>> for i in range(7): print(next(f), end=", ") >>> 55, 89, 144, 233, 377, 610, 987,
Problém s touto funkcí je ten, že neobsahuje definici svého ukončení. Pro její invokaci musíme použít nástroj, který tuto definici obsahuje a tím je v tomto případě jednokrokový příkaz
Generátorový výraz a generátorová funkce vrací generátorový objekt, jímž je pomalu (lazy) vyhodnocovaný iterátor.
Při líném výpočtu (lazy evaluation) se odkládá výpočet výrazu až do chvíle jeho potřeby. Důsledkem je zmenšená potřeba zdrojů (paměti) při zvýšeném výkonu procedury.
Lze sestavit potenciálně nekonečné struktury, např. smyčky - viz fibonacci().
Líný výpočet se obtížně kombinuje s imperativními strukturami jako je ošetření výjímek nebo vstup/výstup; může vytvářet "space leaks" (viz).
Příkladem procedury, uplatňující líný výpočet, je použití slovníku v kapitole
Všechny aktivity spuštěného programu se odvíjejí od textu programu, vyskytujícího se v různých vymezených lexikálních oblastech kódu, zvaných jmenný prostor (namespace), JP.
Těmito oblastmi jsou:
Poznámka: O funkcích a třídách víme (viz 3.1, 12.2), že jejich definice se skládají ze záhlaví a z těla (vnitřního prostoru) funkce či třídy. Jejich lokální oblast je tvořena jejch vnitřním prostorem (tělem).
Objekty jsou přístupné prostřednictvím jmen, které na ně odkazují.
mamoj = "František"
def fun(m)# záhlaví print(m*m)# tělo
V jedné oblasti se nemohou současně vyskytovat dvě stejná jména, odkazující na různé hodnoty:
mam = "Alena"# deklarace přiřazení mam = "Petr"# změna přiřazení, předchozí deklarace neplatí
Mohou se však bez kolize vyskytovat současně v různých oblastech - v různých jmenných prostorech.
Globální proměnná je tvořená v globální oblasti skriptu a je přímo dostupná z globální i z lokální oblasti (funkce) - interpret hledá jméno tam, kde je žádané, případně pokračuje v hierarchicky nadřazené oblasti.
def fun():# lokální prostor s = "Toto je lokální proměnná" print(s)
>>> s = "Zde je globální prostor" >>> fun() Toto je lokální proměnná >>> print (s)# příkaz v globálním prostoru Zde je globální prostor
Vidíme, že jedinečnost jména je dána jeho umístěním. Příkaz print(s) v globálním prostoru ignoruje přiřazení jména v lokálním prostoru, neboť toto jméno je mu přímo nedostuné.
Přítomnost jména ve jmenném prostoru je zapsána ve jmenném registru (JR), jenž má formu slovníku. O existenci tohoto slovníku nás přesvědčí jednoduchá ukázka. Mějme soubor
#global.py # globální prostor a = [1, 2, 3, 4, 5]# globální proměnná def foo():# lokální prostor b = 11# lokální proměnná print(locals()) print(globals()) foo()
# registr globálního prostoru 'global.py' {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__':none, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'F:\\Codetest\\python\\Ukázky\\scopes\\glob_loc.py', 'a': [1, 2, 3, 4, 5], 'foo': <function foo at 0x0000023E6039CFE0>} {'b': 11}# registr lokálního prostoru foo()
Všimněme si, že se proměnná
Zavedené označení výše popsaného slovníku je
Souhrn oblastí, ze kterých je jméno přímo dostupné, se nazývá scope tohoto jména. Do tohoto souhrnu patří jmenný prostor, v němž je jméno deklarováno a všechny níže postavené jmenné prostory.
Dostupnost globální, lokální a vnitřní proměnné si ukážeme na příkladu funkce
glob_local.py # globální prostor glo = "Živijó"# globální proměnná def fun_lok ():# globální proměnná lok = "lokální"# lokální proměnná ## # print("inn = ", inn, sep=", ")# nemá přístup - error def fun_inn ():# lokální proměnná inn = "inner"# vnitřní proměnná # invokace vnořené funkce fun_lok()# invokace vnější funkce
==== RESTART: E:/ALangdoc/Python/scopes/glob_local.py ==== glo, lok = Živijó, lokální glo, lok, inn = Živijó, lokální, inner {'inn': 'inner', 'lok': 'lokální'}
Na příkladu vidíme, že
Z obou prostorů funkce můžeme volat i vestavěná jména z modulu "builtins", jak ukázáno na příkladu funkce locals().
Prostředí
Proměnná
Je-li soubor spuštěn přímo (viz) nebo je otevřena konzola Pythonu, je proměnné __name__ přiřazena hodnota
Je-li realizovaný soubor importován jako modul, je hodnotou proměnné jméno importovaného souboru (bez přípony .py), o čemž se přesvědčíme v konzole Pythonu po importu modulu
>>> __name__# --> '__main__' >>> import sys >>> sys.__name__# --> 'sys'
Kromě prostředí __main__ existuje ještě funkce
Proměnná __name__ se dvěma možnými hodnotami (__main a jméno modulu) umožňuje variabilně zapojovat další kód do aktuálně prováděného zdrojového kódu a to buď konkretním přikazem v těle smyčky
nebo pomocí funkce main(), která takový příkaz obsahuje:if __name__ == "__main__":text zdrojového kódu
def krok_1(): print("Provádí se první krok ...") def krok_2(): print("Provádí se druhý krok ...") def main(): krok_2()if __name__ == "__main__": main()
Introspekce Pythonu je akt zkoumání obsahu a vlastností jednotlivých jeho objektů. Za tímto účelem disponuje Python řadou vestavěných funkcí, z nichž některé již známe.
>>> omen = "Alenka" >>> dir(omen) ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', ...
>>> isinstance(5, int) True
>>> getattr(omen, "__doc__") "str(object='') -> str\nstr(bytes_or_buffer[, ... ... sys.getdefaultencoding().\nerrors defaults to 'strict'."
Docstring je krátká informace ve formátu řetězce (
Při rozvoji programu se s oblibou provádí testování vybraných úseků zdrojového kódu. Pro toto testování poskytuje Python moduly doctest a uniclr-ttest.
Popíšeme si práci s modulem
Modul
def is_divisible_by_2_or_5 (n):""" >>> is_divisible_by_2_or_5(8) True >>> is_divisible_by_2_or_5(7) False >>> is_divisible_by_2_or_5(5) True """ return n % 2 == 0or n % 5 == 0if __name__ == '__main__':import doctest doctest.testmod()
Poslední tři řádky spouští celou parádu. Umisťujeme je na konec každého souboru, který obsahuje doctesty.
Pokud procedura zjistí shodu mezi zkoumanými vzorky a zadanými výsledky, reaguje "mlčením" nebo je-li v konzole evokována funkce "doctest.testmod()", vrátí stručný komentář o průběhu
>>> doctest.testmod()TestResults(failed=0, aclr-ttempted=3)
Pokud narazí na rozpor, spustí rozsáhlé chybové hlášení.
Spuštění neúspěšného skriptu vyprodukuje například následující výstup:
Failed example: is_divisible_by_2_or_5(7) Expected: True Got: False ***********************************************************1 items had failures: 1 of 3 in __main__.is_divisible_by_2_or_5 ***Test Failed*** 1 failures.
stvoří tento výstup
1 1 2 3 3 6 4 10 5 15
if __name__ == '__main__': import doctest doctest.testmod()
Funkce
def num_digits (n): """ >>> num_digits(12345) 5 >>> num_digits(0) 1 >>> num_digits(-12345) 5 """
def num_even_digits (n): """ >>> num_even_digits(123456) 3 >>> num_even_digits(2468) 4 >>> num_even_digits(1357) 0 >>> num_even_digits(2) 1 >>> num_even_digits(20) 2 """
Nutno zajistit, aby mezi číslicemi výstupu byly mezery a aby za poslední číslicí žádná mezera nebyla. Numerický argument funkce nutno před manipulací přetvořit nadef print_digits (n): """ >>> print_digits(13789) 9 8 7 3 1 >>> print_digits(39874613) 3 1 6 4 7 8 9 3 >>> print_digits(213141) 1 4 1 3 1 2 """
Svá řešení ověřte pomocí doctestů.def sum_of_squares_of_digits (n): """ >>> sum_of_squares(1) 1 >>> sum_of_squares(9) 81 >>> sum_of_squares(11) 2 >>> sum_of_squares(121) 6 >>> sum_of_squares(987) 194 """
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |