Dilema I
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
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: 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:
Ú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
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. dunder metod (double underscore), kterým se taky někdy říká magické metody, ale nic magického na nich není (viz též 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
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 ([Kubias2008] nebo 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ř. Python 3 tutoriálem, nebo jiným podobným zdrojem veškeré moudrosti
Interaktivní cvičení
Na codecademy pokračujte v interaktivním kurzu Pythonu 2 nebo 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:
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í!