IB111 Úvod do programování skrze Python Přednáška 8 Správa paměti (proměnné podrobněji) Práce se soubory Nikola Beneš 6. listopad 2017 IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 1 / 28 Proměnné a paměť 0x1e 0x1f 0x20 0x21 ... ... IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 2 / 28 Proměnné Proměnné něco, co drží hodnotu jejich hodnota se může během výpočtu měnit Názvy proměnných (v Pythonu) posloupnost písmen, číslic a znaků '_' bez mezer, více slov pomocí: podtržítek: dlouhy_nazev_promenne (PEP8) střídání velikosti písmen: dlouhyNazevPromenne nelze používat rezervovaná klíčová slova jazyka False class finally is return None continue for lambda try True def from nonlocal while and del global not with as elif if or yield assert else import pass break except in raise IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 3 / 28 Globální a lokální proměnné Globální proměnné definovány globálně (tj. ne uvnitř funkce) jsou viditelné kdekoli v programu Lokální proměnné definovány uvnitř funkce jsou viditelné jen ve své funkci Obecněji: proměnné jsou viditelné v rámci svého bloku blokem můžou být: moduly (soubory se zdrojovým kódem) funkce třídy (o těch se dozvíme později) a jiné (závisí na konkrétním jazyce) IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 4 / 28 Globální a lokální proměnné v Pythonu Příklad 1 a = "This is global." def example1(): b = "This is local." print(a) print(b) example1() # This is global. # This is local. print(a) # This is global. print(b) # CHYBA! # NameError: name 'b' is not defined IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 5 / 28 Globální a lokální proměnné v Pythonu Příklad 2 a = "Think global." def example2(): a = "Eat local." print(a) print(a) # Think global. example2() # Eat local. print(a) # Think global. vytváříme novou lokální proměnnou, neměníme tu globální IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 6 / 28 Globální a lokální proměnné v Pythonu Příklad 3 jak měnit globální proměnné? a = "Think global." def example3(): global a a = "Eat local." print(a) print(a) # Think global. example3() # Eat local. print(a) # Eat local. IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 7 / 28 Globální a lokální proměnné v Pythonu Příklad 4 lokální proměnná vzniká přiřazením kdekoli uvnitř funkce a = "Think global." def example4(change_opinion=False): print(a) if change_opinion: a = "Eat local." print("Changed opinion:", a) print(a) # Think global. example4() # CHYBA! # UnboundLocalError: local variable 'a' referenced before # assignment IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 8 / 28 Globální a lokální proměnné Doporučení pokud možno nepoužívat globální proměnné globální konstanty jsou v pořádku konvence pojmenování konstant: velkými písmeny Proč? porušují lokalitu kódu potenciální chyby nečitelnost Alternativy předávání parametrů funkcím a vracení hodnot z funkcí objekty (o těch si něco málo řekneme později) a další (nad rámec předmětu) statické proměnné (C, C++, Java, …) návrhový vzor Singleton … IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 9 / 28 Globální a lokální proměnné proměnné v Pythonu jsou interně uloženy ve slovnících přístup ke slovníkům: locals(), globals() def example5(): n = 100 dog = "Laika" print(locals()) n = 1000 my_list = [3, 1, 4, 1, 5] example5() print(globals()) IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 10 / 28 Proměnné podrobněji: připomenutí Ilustrace přiřazení Jazyk C Proměnné jako hodnoty int a, b; a = 1; a = 2; b = a; a 1 b a 2 b a 2 b 2 Jazyk Python Proměnné jako odkazy a = 1; a = 2; b = a; a 1 a 1 2 a b 1 2 IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 11 / 28 Proměnné podrobněji Příklad a = 1000 b = a print(a, b) print(id(a), id(b)) b += 1 print(a, b) print(id(a), id(b)) a = [1] b = a print(a, b) print(id(a), id(b)) b.append(2) print(a, b) print(id(a), id(b)) [další ukázky, použití http://pythontutor.com] IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 12 / 28 Proměnné podrobněji v čem je rozdíl? my_list.sort() my_list = sorted(my_list) na první pohled se může zdát, že žádný není ale co když existuje ještě jiná proměnná, která se odkazuje na tentýž seznam? [ukázka] IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 13 / 28 Předávání parametrů funkcím Způsoby předávání parametrů hodnotou (call by value) předá se hodnota proměnné (kopie) standardní v C, C++, apod. odkazem (call by reference) předá se odkaz na proměnnou lze použít v C++ jiné možnosti (jménem, hodnotou-výsledkem, …) jazyk Python: něco mezi voláním hodnotou a referencí podobně funguje např. Java někdy nazýváno call by object sharing IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 14 / 28 Předávání parametrů funkcím Předávání parametrů hodnotou parametr je vlastně lokální proměnná funkce má svou vlastní lokální kopii předané hodnoty funkce nemůže změnit hodnotu předané proměnné Předávání parametrů odkazem nepředává se hodnota, ale odkaz na proměnnou změny parametru jsou ve skutečnosti změny předané proměnné IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 15 / 28 Příklad předávání v C++ #include void fun(int a, int& b) { a = a + 1; b = b + 1; } int main() { int a = 1; int b = 1; std::cout << "a: " << a << ", b: " << b << "\n"; fun(a, b); std::cout << "a: " << a << ", b: " << b << "\n"; } IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 16 / 28 Předávání parametrů funkcím Předávání parametrů v Pythonu paramater drží odkaz na předanou proměnnou změna parametru změní i předanou proměnnou pro neměnné typy tedy v podstatě funguje jako předávání hodnotou čísla, řetězce, ntice (tuples) pro měnitelné typy jako předávání odkazem ale pozor! přiřazení znamená změnu odkazu def fun(s): s.append(3) s = [42, 17] s.append(9) print(s) t = [1, 2] fun(t) print(t) IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 17 / 28 Předávání parametrů funkcím Operátor += různé chování pro neměnné typy a pro seznamy def increment(x): print(x, id(x)) x += 1 print(x, id(x)) p = 2015 increment(p) print(p, id(p)) def add_to_list(s): print(s, id(s)) s += [1] print(s, id(s)) t = [1, 2, 3] add_to_list(t) print(t, id(t)) IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 18 / 28 Předávání parametrů funkcím Pozor na rozdíl mezi = a += u seznamů def add_to_list1(s): print(s, id(s)) s += [1] print(s, id(s)) t = [1, 2, 3] add_to_list1(t) print(t) # výsledek je [1, 2, 3, 1] def add_to_list2(s): print(s, id(s)) s = s + [1] print(s, id(s)) t = [1, 2, 3] add_to_list2(t) print(t) # jaký je výsledek? IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 19 / 28 Správa paměti Různé přístupy ke správě paměti manuální – funkce pro přidělení/uvolnění paměti automatická – paměť je uvolněna na konci života proměnné automatická – počítání referencí kolik částí programu ještě s danou pamětí pracuje pokud už nikdo, paměť je uvolněna automatická – garbage collection jednou za čas se uklidí nepoužívaná paměť Správa paměti v Pythonu automatická – počítání referencí + někdy i větší úklid počet referencí sys.getrefcount(object) IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 20 / 28 Správa paměti v Pythonu Zvýšení počtu odkazů vytvoření a = "Hello!" vytvoření aliasu b = a předání funkci fun(a) vložení do složeného prvku s = [42, a, -7] Snížení počtu odkazů ukončení platnosti lokální proměnné konec funkce smazání proměnné del a přiřazení jiné hodnoty aliasu b = "Aloha!" odstranění ze složeného prvku s.remove(a) odstranění složeného prvku del s IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 21 / 28 Kopírování objektů Vytvoření aliasu b = a odkaz na stejnou věc Mělká kopie b = a[:] nebo b = list(a) vytváříme nový seznam, ale prvky tohoto seznamu jsou aliasy obecně i pro jiné typy než seznamy (knihovna copy) b = copy.copy(a) Hluboká kopie kompletní kopie všech dat – jak? obecné řešení (opět knihovna copy) b = copy.deepcopy(a) IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 22 / 28 Práce se soubory IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 23 / 28 Práce se soubory v Pythonu Způsob práce otevření souboru práce se souborem (čtení / zápis) zavření souboru >>> my_file = open("/tmp/my_file", "w") >>> print(my_file) <_io.TextIOWrapper name='/tmp/my_file' mode='w' encoding='UTF>>> my_file.write("Hasta la vista!\n") >>> my_file.close() IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 24 / 28 Práce se soubory v Pythonu Otevření souboru open(jmeno, zpusob) jméno souboru: řetězec (pozor na Windows a '\\') způsob otevření: čtení ("r") zápis ("w") – přepíše soubor, pokud není, vytvoří jej přidání na konec ("a") čtení i zápis ("r+", "w+" nebo "a+") binární režim (přidat "b" k některému způsobu) IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 25 / 28 Práce se soubory v Pythonu Čtení ze souboru f.read(pocet) – přečte daný počet znaků f.read() – přečte celý soubor, vrací řetězec f.readline() – přečte celý jeden řádek f.readlines() – přečte všechny řádky, vrací seznam řádků Zápis do souboru f.write(text) – zapíše řetězec do souboru neukončuje řádky, je třeba explicitně použít '\n' Jiné f.tell() – aktuální pozice v souboru f.seek(pozice) – přesun pozice v souboru IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 26 / 28 Práce se soubory v Pythonu Iterace po řádcích for line in my_file: print(line) Speciální blok with při jeho použití není třeba soubor zavírat zavře se sám při ukončení bloku with open("/tmp/my_file", "r") as my_file: lines = my_file.readlines() print(lines) IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 27 / 28 Shrnutí Proměnné lokální vs. globální (používejte jen jako konstanty) v Pythonu: drží odkaz na hodnotu Předávání parametrů v Pythonu: něco mezi hodnotou a odkazem (call by sharing) Správa paměti v Pythonu: počítání referencí, automatický úklid Kopírování objektů mělká vs. hluboká kopie užitečná knihovna copy Práce se soubory otevření / zavření souboru; užitečný blok with zápis, čtení IB113 přednáška 8: správa paměti, práce se soubory 6. listopad 2017 28 / 28