====== Dilema I ====== [[courses:b4b33rph:internal:cviceni:program_po_tydnech:tyden_02|Učitelská verze stránky]] ===== Výsledky učení ===== Po tomto cvičení student * chápe zadání úlohy Vězňovo dilema a rozumí, jakým způsobem bude jeho hráč testován, * využívá ''for'' cyklus k implementaci jednoduchých opakujících se činností, * je si vědom, že je třeba kódy testovat, * implementuje jednoduché vlastní datové typy pomocí tříd, * chápe funkci ''__dunder__'' metod a není překvapen, když je vidí. ===== Program ===== * diskuse problémů * diskuse prvního DÚ s Lenkou * vyjasnění zadání úlohy Vězňovo dilema * procvičování ''for'' cyklů * třída pro komplexní čísla a jejich sčítání, násobení, ... * procvičování základních datových typů ===== Hádanka ====== /* Pro vyplnění formuláře je třeba se přihlásit na Google pod Vaší FEL identitou [[https://forms.gle/kFqxMq54p7hjByPu6|101]] [[https://forms.gle/3nLTaoxHoVa3zQVk7|102]] [[https://forms.gle/QaZvFUtncp1Ne1CH7|103]] [[https://forms.gle/vzsGD3QyLgcqMk1g7|104]] [[https://forms.gle/oMqTMgeh4ao4uiwL8|105]] [[https://forms.gle/uyin2XUR2RuBFCna6|106]] [[https://forms.gle/MuffuZrZW4u4wWx8A|107]] [[https://forms.gle/4kfZisGQAbhkvdvHA|108]] [[https://forms.gle/yARdGc2Gxtt5qAudA|109]] */ Zadání hádanky se dozvíte na cvičení. ===== Lenka ===== * Je všem jasné, jaké pořadí odpovědí bylo správné? * Proč jste pro své řešení volili malá/velká písmena? * Odpovědi velkými písmeny získávají svou odměnu jen v případě, že procento odpovědí velkými písmeny přesáhne jistý práh. Pro jakou hodnotu prahu se pro vás osobně láme rozhodnutí mezi velkými a malými písmeny? ===== Vězňovo dilema ===== Na přednášce byl prezentován problém vězňova dilematu. Přečtěte si pozorně zadání úlohy: [[..:veznovo_dilema:start| Vězňovo dilema]]. Ptejte se na nejasnosti. ==== Jak splnit zadání úlohy ==== Několik základních kontrolních bodů, kterých je rozumné se držet: * správně pojmenovat soubor * správně pojmenovat funkce, třídy a metody (pozor na malá a velká písmena), které jsou požadovány ve specifikacích * správné parametry metody (self)! * výstup metody * správné odsazení * nepřepisovat vnitřní proměnné nebo funkce Pythonu ==== Další známé hry ==== Další hry ala vězňovo dilema pro vaši inspiraci: * [[http://en.wikipedia.org/wiki/Rock,_Paper,_Scissors|Rock paper scissors]] * [[http://en.wikipedia.org/wiki/Chicken_(game)|Game of chicken]] * [[http://en.wikipedia.org/wiki/Matching_pennies|Matching pennies]] * [[http://en.wikipedia.org/wiki/Coordination_game|Coordination game]] * [[http://en.wikipedia.org/wiki/Ultimatum_game|Ultimatum game]] * [[http://en.wikipedia.org/wiki/Pirate_game|Pirate game]] ====== Úkoly na cvičení ====== ===== For cykly ===== ==== Seznam a jeho procházení ==== - Vytvořte proměnnou ''years'' obsahující seznam několika letopočtů, které jsou pro vás něčím významné, např. roky narození vašich blízkých. - Zjistěte, kolik prvků seznam obsahuje. Jakou funkci Pythonu k tomu použijete? - Vypište jednotlivé letopočty pomocí ''for''-cyklu, každý na jeden řádek. Jaké různé způsoby řešení této úlohy vás napadají? - Upravte kód tak, aby se spolu s letopočtem vypisoval i index prvku v poli. Jaké různé způsoby řešení této úlohy vás napadají? - Zkuste změnit hodnotu proměnné ''years'' tak, aby váš kód skončil chybou, nebo se choval z vašeho pohledu neočekávaně. Zkuste porozumět chybové hlášce/důvodu, proč se kód chová právě takto. K porozumění/vysvětlení můžete využít dokumentaci k Pythonu, internetová fóra, i umělou inteligenci. ==== Funkce pracující se seznamem ==== - Doplňte implementaci následující funkce pro nalezení největšího prvku v kolekci. Je funkce dostatečně specifikovaná? Co ještě potřebujete vědět? def find_max(collection): """ Return a tuple: the maximum item found in the collection, and its index """ - Opět, zkuste změnit hodnotu proměnné ''years'' tak, aby funkce ''find_max'' selhala nebo vrátila nečekaný výsledek. - Vytvořte obdobnou funkci ''find_all_max(collection)'', která nebude vracet jen jeden index maximálního prvku, ale seznam indexů všech výskytů maximálního prvku. ===== Datové typy ===== ==== Základní datové typy Pythonu ==== * Jaké základní datové typy Python obsahuje? ++ Typy: | celá a desetinná čísla, řetězce, pravdivostní hodnoty (True/False)++ * Co když chcete vytvořit vlastní složený datový typ? ===== Jednoduchá třída ===== Navrhněte a implementujte třídu ''ComplexNumber''. ==== K rozmyšlení ==== - Čím je instance komplexního čísla definována? Jaké bude mít členské proměnné? - Jaké má vlastnosti? - Jaké má schopnosti? Jaké operace lze dělat s komplexním číslem? ==== Implementace ==== Pokuste se třídu implementovat a postupně rozšiřujte její schopnosti. Neděste se, vyučující vám na cvičení ukáží jak na to. * ++ Inicializace | Implementujte metodu ''__init__(self, re, im)''. Co vidíte při spuštění příkazů: >>> a = ComplexNumber(3,4) >>> print(a.re) >>> print(a.im) >>> print(a)++ * ++ Čitelná reprezentace | Nebylo by hezké, kdyby instance komplexního čísla uměla vytvořit hezky čitelnou řetězcovou reprezentaci? Implementujte metodu ''to_string(self)'' tak, aby kód fungoval takto: >>> a = ComplexNumber(3,4) >>> print(a.to_string()) 3+4i++ * ++ Absolutní hodnota komp. čísla | Implementujte metodu ''abs(self)'', která vypočte a vrátí absolutní hodnotu komplexního čísla: >>> a = ComplexNumber(3,4) >>> print(a.abs()) 5++ * ++ Inkrement reálné a imaginární části | Implementujte metodu ''inc_parts(self, re, im)'', která zvětší hodnoty reálné a imaginární části o zadaná čísla: >>> a = ComplexNumber(1,2) >>> a.inc_parts(2,2) >>> print(a.to_string()) 3+4i++ * ++ Inkrement komp. čísla jiným komplexním číslem | Implementujte metodu ''inc(self, other)'', která zvětší hodnoty reálné a imaginární části o hodnoty reálné a imaginární části druhého komplexního čísla předaného jako argument: >>> a = ComplexNumber(1,2) >>> b = ComplexNumber(2,2) >>> a.inc(b) >>> print(a.to_string()) 3+4i++ * ++ Součet komplexních čísel | Implementujte metodu ''add(self, other)'', která sečte komplexní číslo ''self'' s komplexním číselm ''other'' a výsledek vrátí jako novou instanci komplexního čísla: >>> a = ComplexNumber(1,2) >>> b = ComplexNumber(2,2) >>> c = a.add(b) >>> print(c.to_string()) 3+4i++ ==== "Dunder" metody ==== Možnost hezky vypsat komplexní číslo, zjistit jeho velikost, nebo sečíst 2 komplexní čísla pomocí námi definovaných metod je šikovná, ale ještě šikovnější by bylo, kdybychom mohli * místo ''print(a.to_string())'' napsat prostě ''print(a)'', * místo ''a.abs()'' využít funkci ''abs(a)'', což je obvyklý způsob, jak zjistit absolutní hodnotu tam, kde to dává smysl, nebo * místo ''a.add(b)'' psát prostě ''a+b''. Python k tomu nabízí prostředky ve formě tzv. [[https://www.geeksforgeeks.org/dunder-magic-methods-python/|dunder metod]] (double underscore), kterým se taky někdy říká //magické metody//, ale nic magického na nich není (viz též [[https://docs.python.org/3/reference/datamodel.html#special-method-names|oficiální dokumentace]]). Jsou to metody, které se obvykle nevolají přímo, ale volá je interpret Python v jistých situacích. Jednu z nich už jste poznali - metodu ''__init__()'', kterou Python volá po vytvoření nové instance nějaké třídy a jejímž úkolem je instanci inicializovat. Pokuste se naši třídu ''ComplexNumber'' vybavit těmito metodami: * ++ __str__(self) | Buď přejmenujte metodu ''to_string()'' nebo ji v metodě ''__str__'' zavolejte. Měl by pak fungovat následující kód: >>> a = ComplexNumber(3,4) >>> print(a) 3+4i++ * ++ __abs__(self) | Buď přejmenujte metodu ''abs(self)'' nebo ji v metodě ''__abs__'' zavolejte. Měl by pak fungovat následující kód: >>> a = ComplexNumber(3,4) >>> print(abs(a)) 5++ * ++ __add__(self, other) | Buď přejmenujte metodu ''add(self, other)'' nebo ji v metodě ''__add__'' zavolejte. Měl by pak fungovat následující kód: >>> a = ComplexNumber(1,2) >>> b = ComplexNumber(2,2) >>> c = a + b >>> print(c) 3+4i++ * Dokážete nyní odhadnout, k čemu slouží metoda ''__mul__(self, other)'' a pro jaký kód ji Python zavolá? Uměli byste tuto metodu implementovat pro třídu ''ComplexNumber''? Zkuste to, není to nic těžkého. * Když umíme dvě komplexní čísla sečíst, umíme je i odečíst, nebo ne? Zkuste, co udělá následující kód: >>> a = ComplexNumber(1,2) >>> b = ComplexNumber(2,2) >>> c = a - b >>> print(c)Dokážete třídu upravit tak, aby tento kód fungoval? ====== Domácí úkol ====== ===== Skalární součin vektorů ===== * Vytvořte modul ''vectors.py''. * V něm bude definice třídy ''MyVector''. * Konstruktor bude akceptovat (navíc k ''self'') jeden parametr, kterým bude seznam s prvky vektoru. * Metoda ''get_vector(self)'' navrátí seznam obsahující prvky vektoru. * Pomocí metody ''__mul__(self, other)'' implementujte [[https://en.wikipedia.org/wiki/Dot_product|skalární součin]] dvou objektů typu ''MyVector''. Výstupem je tedy skalár (jedno číslo). V metodě počítejte s libovolnou délkou vektorů, oba budou stejné, ale libovolné délky (ne jen 3-dimenzionální). * Neměli byste cítit potřebu importovat v modulu ''vectors.py'' jiné moduly (snad kromě modulu ''typing''). Požadovanou funkcionalitu máte implementovat sami, nikoli ji delegovat na nějaké jiné knihovny, které by práci udělali za vás. * Soubor nahrajte do BRUTE do požadovaného termínu. * BRUTE vám kód ihned ohodnotí, případně několik sekund počkejte. * Za správně vyřešenou úlohu získáte až 2 body. Nazapomeňte na vlastní kontrolu kódu, nespoléhejte pouze na kontrolu v BRUTE. Třeba něco jako: if __name__ == "__main__": vec1 = MyVector([1,2,3]) # vektory mohou byt i jine dimenze nez 3! vec2 = MyVector([3,4,5]) print(vec1.get_vector()) # priklad ziskani seznamu dot_product = vec1*vec2 # vypocet skalarniho soucinu, pretizeny operator *, vola se __mul__ print(dot_product) # jen kontrolni vypis ===== Čtení ===== Přečtěte zbytek vašeho vybraného Python tutorialu ({[b4b33rph:Kubias2008]} nebo [[https://naucse.python.cz/course/pyladies/|Nauč se Python!]]). Nemusíte úplně rozumět všemu, ani si pamatovat vše zpaměti. Měli byste mít natrénován postup jak si dohledat potřebné informace, mít natrénovanu práci s např. [[http://docs.python.org/py3k/tutorial/index.html|Python 3 tutoriálem]], nebo jiným podobným zdrojem veškeré moudrosti ;-) ===== Interaktivní cvičení ===== Na //codecademy// pokračujte v [[https://www.codecademy.com/learn/learn-python|interaktivním kurzu Pythonu 2]] nebo [[https://www.codecademy.com/learn/learn-python-3|Pythonu 3]], pokud k němu máte přístup. Předpokládáme, že otázky, které jste měli po části kurzu z minulého týdne, jste položili na fóru nebo právě dnes na cvičení a že tudíž můžete pokračovat dál sekcemi: * Functions * Taking a vacation * Python lists and dictionaries * A day at the supermarket * Student becomes the teacher * Lists and functions * Loops Opět se pokuste dostat co nejdál. Stále platí, že tato cvičení vám mají především pomoci **identifikovat věci, kterým nerozumíte**. **Pokládejte otázky na Discordu, na fóru nebo na cvičení!**