IB111 Úvod do programování skrze Python Přednáška 7 Správa paměti (proměnné podrobněji) Práce se soubory Nikola Beneš 2. listopad 2016 IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 1 / 28 Proměnné a paměť 0x1e 0x1f 0x20 0x21 ... ... IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 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 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 IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 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) IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 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 IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 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í IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 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. IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 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 IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 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 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 … IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 9 / 28 Proměnné podrobněji Proměnné v různých jazycích pojmenované místo v paměti odkaz na místo v paměti (Python) kombinace obou možností Přiřazení proměnné ve stylu C: změna obsahu paměti proměnné ve stylu Pythonu: změna odkazu na jiné místo v paměti IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 10 / 28 Proměnné podrobněji 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 IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 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] IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 12 / 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 IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 13 / 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é IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 14 / 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"; } IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 15 / 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) IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 16 / 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)) IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 17 / 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? IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 18 / 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) IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 19 / 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 IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 20 / 28 Správa paměti v Pythonu Pamatování některých hodnot některé hodnoty si Python automaticky udržuje v paměti a nevytváří je znovu kvůli vyšší rychlosti / výkonu často používané hodnoty čísla mezi -5 a 256 prázdný řetězec, jednotlivé znaky krátké řetězce se vytváří jen jednou import sys a = 1 print(sys.getrefcount(a)) a = "" print(sys.getrefcount(a)) IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 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) IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 22 / 28 Práce se soubory IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 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() IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 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) IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 25 / 28 Práce se soubory v Pythonu Čtení ze souboru read(pocet) – přečte daný počet znaků read() – přečte celý soubor, vrací řetězec readline() – přečte celý jeden řádek readlines() – přečte všechny řádky, vrací seznam řádků Zápis do souboru write(text) – zapíše řetězec do souboru neukončuje řádky, je třeba explicitně použít '\n' Jiné tell() – aktuální pozice v souboru seek(pozice) – přesun pozice v souboru IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 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) IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 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í IB111 přednáška 7: správa paměti, práce se soubory 2. listopad 2016 28 / 28