diff --git a/09-objekty/09-objekty.tex b/09-objekty/09-objekty.tex new file mode 100644 index 0000000000000000000000000000000000000000..3064f49c3dec3f15fad18f5268f1f0d72f972952 --- /dev/null +++ b/09-objekty/09-objekty.tex @@ -0,0 +1,297 @@ +\documentclass{beamer} +\usepackage[utf8]{inputenc} +\usepackage[czech]{babel} +\usepackage{palatino} +\usepackage{verbatim} +\usetheme{Warsaw} +\title{Programování 1: Třídy a objekty} +\author[Martin Mareš]{Martin Mareš\\\texttt{mj@ucw.cz}} +\institute{Katedra Aplikované Matematiky\\MFF UK Praha} +\date{2019} +\begin{document} +\setbeamertemplate{navigation symbols}{} +\setbeamertemplate{footline}{} +\setbeamerfont{title page}{family=\rmfamily} +\shorthandoff{"} + +\begin{frame} +\titlepage +\end{frame} + +\input ../slidemac.tex + +% ---------------------------------------------------------------------- + +\begin{frame}{Definice třídy} + +\verbatiminput{trida_def.py} + +~ + +Definujeme nový typ, který má nějaké {\bf atributy} (vlastnosti) +a~{\bf metody} (funkce, operace). + +\end{frame} + +% ---------------------------------------------------------------------- + +\begin{frame}{Objekty} + +Vytvoříme nový objekt (automaticky zavolá {\tt \_\_init\_\_}): +\smallskip + +\py{% +azor = Zvire("Azor", "Haf!")\\ +azor +}{% +<Zvire object at 0x7ffff71ce2b0> +} + +\smallskip +Atributy objektu: +\smallskip + +\py{% +azor.zvuk +}{% +'Haf!' +} + +\py{% +azor.zvuk = "Hafff!" +}{% +} + +\smallskip +Metody objektu: +\smallskip + +\py{% +azor.slysi\_na('Příšero') +}{% +False +} + +\py{% +azor.ozvi\_se() +}{% +Azor říká: Hafff! +} + +\end{frame} + +% ---------------------------------------------------------------------- + +\begin{frame}{Identita objektu} + +\py{% +jezevcik = Zvire("Špagetka", "haf")\\ +bernardyn = Zvire("Bernard", "HAF!!!")\\ +maxipes = bernardyn\\ +maxipes.jmeno = "Fík"\\ +bernardyn.jmeno +}{% +'Fík' +} + +\py{% +type(jezevcik) +}{% +<class 'Zvire'> +} + +\py{% +id(jezevcik), id(bernardyn), id(maxipes) +}{% +(737339253592, 737339253704, 737339253704) +} + +\py{% +bernardyn is maxipes +}{% +True +} + +\py{% +bernardyn is jezevcik +}{% +False +} + +\end{frame} + +% ---------------------------------------------------------------------- + +\begin{frame}{Protokol pro převod na řetězec} + +\verbatiminput{trida_str.py} + +\medskip + +\py{% +hroch = Zvire("Hippo", "Humpf!")\\ +hroch +}{% +Pes(Hippo, Humpf!) +} + +\py{% +print(hroch) +}{% +Hippo +} + +\end{frame} + +% ---------------------------------------------------------------------- + +\begin{frame}{Protokol pro operátory} + +\verbatiminput{trida_op.py} + +\medskip + +\py{% +hroch1 = Zvire("Hippo", "Humpf!")\\ +hroch2 = Zvire("Hippo", "Humpf!")\\ +hroch1 is hroch2 +}{% +False +} + +\py{% +hroch1 == hroch2 +}{% +True +} + +\smallskip + +Podobně jde předefinovat všechny operátory včetně {\bf []} a {\bf .} + +\end{frame} + +% ---------------------------------------------------------------------- + +\begin{frame}{Dokumentační komentáře} + +\verbatiminput{trida_doc.py} + +\py{% +help(Zvire) +}{% +} + +\py{% +z = Zvire("Lenochod", "Zzz...")\\ +help(z.slysi\_na) +}{% +} + +\end{frame} + +% ---------------------------------------------------------------------- + +\begin{frame}{Dědičnost} + +\verbatiminput{trida_dedicnost.py} + +\py{% +k = Kocka("Příšerka", "Mňauuu")\\ +k.slysi\_na("Příserka") \cmt{(speciální kočičí verze)} +}{% +False +} + +\py{% +k.ozvi\_se() \cmt{(původní zvířecí metoda)} +}{% +Příšerka říká: Mňauuu +} + +\end{frame} + +% ---------------------------------------------------------------------- + +\begin{frame}{Jak to funguje uvnitř} + +{\bf Prostory jmen (namespaces):} + +\medskip + +\begin{itemize} +\item Zabudované funkce (třeba {\tt print}) +\item Globální jména (proměnné, funkce) +\item Lokální jména uvnitř funkce +\item Jména definovaná v~třídě +\item Jména definovaná v~objektu +\end{itemize} + +\medskip + +Obyčejné jméno se hledá ve všech prostorech, které jsou na daném +místě v~programu \uv{vidět}. + +\medskip + +{\tt objekt.jméno} se hledá: + +\medskip + +\begin{itemize} +\item V~prostoru atributů objektu +\item V~prostoru příslušné třídy +\item V~prostorech všech nadřazených tříd +\item Pozor, třída může mít více přímých předků! +\end{itemize} + +\end{frame} + +% ---------------------------------------------------------------------- + +\begin{frame}{Jak to funguje uvnitř: zabudované typy} + +{\bf Zabudované typy jako int, str apod.} jsou rovněž třídy. +Volání {\tt int()} nebo {\tt int("1")} je prostě vytvoření objektu dané třídy. + +\medskip + +{\bf Třída je také objekt:} + +\medskip + +\begin{itemize} +\item Lze psát třeba {\tt Zvire.slysi\_na}. +\item Uvnitř třídy můžeme přiřazovat do proměnných, ty jsou vidět jako + atributy třídy. +\item Vnitřek definice {\tt class} je ve skutečnosti normální program, + který se provádí uvnitř prostoru jmen třídy. +\end{itemize} + +\medskip + +{\bf Modul je také objekt:} + +\medskip + +\begin{itemize} +\item {\tt import math} ho vytvoří +\item {\tt math.random} je formálně přístup k~atributu +\end{itemize} + +\medskip + +{\bf Volání metody:} + +\medskip + +\begin{itemize} +\item {\tt alik.ozvi\_se} vytvoří pomocnou funkci, která zavolá + {\tt Zvire.ozvi\_se} a doplní jako první argument {\tt alik}. +\end{itemize} + +\end{frame} + +% ---------------------------------------------------------------------- + +\end{document} diff --git a/09-objekty/Makefile b/09-objekty/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e48df267f35fff03c55f4dbbc81e15c050a159c7 --- /dev/null +++ b/09-objekty/Makefile @@ -0,0 +1,3 @@ +SLIDES=09-objekty.pdf + +include ../Makerules diff --git a/09-objekty/trida.py b/09-objekty/trida.py new file mode 100644 index 0000000000000000000000000000000000000000..c98e92b0fda39e273ec1f76999898e71706101f3 --- /dev/null +++ b/09-objekty/trida.py @@ -0,0 +1,35 @@ +class Zvire: + """Vytvoří zvíře s danými vlastnostmi.""" + + def __init__(self, jmeno, zvuk): + self.jmeno = jmeno + self.zvuk = zvuk + + def slysi_na(self, jmeno): + """Slyší zvíře na dané jméno?""" + return self.jmeno == jmeno + + def ozvi_se(self): + """Vydá zvuk daného zvířete.""" + print(self.jmeno, "říká:", self.zvuk) + + def __str__(self): + return self.jmeno + + def __repr__(self): + return f"Pes({self.jmeno}, {self.zvuk})" + + def __eq__(self, other): + return self.jmeno == other.jmeno and \ + self.zvuk == other.zvuk + +class Kocka(Zvire): + """Vytvoří kočku s danými vlastnostmi.""" + + def __init__(self, jmeno, zvuk): + Zvire.__init__(self, jmeno, zvuk) + self.pocet_zivotu = 9 + + def slysi_na(self, jmeno): + # Copak kočka slyší na jméno? + return False diff --git a/09-objekty/trida_dedicnost.py b/09-objekty/trida_dedicnost.py new file mode 100644 index 0000000000000000000000000000000000000000..802fbaaff05c6c39ba71b83088a7024ec78310be --- /dev/null +++ b/09-objekty/trida_dedicnost.py @@ -0,0 +1,9 @@ +class Kocka(Zvire): + + def __init__(self, jmeno, zvuk): + Zvire.__init__(self, jmeno, zvuk) + self._pocet_zivotu = 9 # interní + + def slysi_na(self, jmeno): + # Copak kočka slyší na jméno? + return False diff --git a/09-objekty/trida_def.py b/09-objekty/trida_def.py new file mode 100644 index 0000000000000000000000000000000000000000..b2f073068d5993a59f7c098f0eb3799416230c56 --- /dev/null +++ b/09-objekty/trida_def.py @@ -0,0 +1,11 @@ +class Zvire: + + def __init__(self, jmeno, zvuk): + self.jmeno = jmeno + self.zvuk = zvuk + + def slysi_na(self, jmeno): + return self.jmeno == jmeno + + def ozvi_se(self): + print(self.jmeno, "říká:", self.zvuk) diff --git a/09-objekty/trida_doc.py b/09-objekty/trida_doc.py new file mode 100644 index 0000000000000000000000000000000000000000..ca433f1e07bd08ca2c80f134048f4a22168385f1 --- /dev/null +++ b/09-objekty/trida_doc.py @@ -0,0 +1,10 @@ +class Zvire: + """Vytvoří zvíře s danými vlastnostmi.""" + + def __init__(self, jmeno, zvuk): + self.jmeno = jmeno + self.zvuk = zvuk + + def slysi_na(self, jmeno): + """Slyší zvíře na dané jméno?""" + return self.jmeno == jmeno diff --git a/09-objekty/trida_op.py b/09-objekty/trida_op.py new file mode 100644 index 0000000000000000000000000000000000000000..ae93a77b004999b2d6f19f9a71ff5fc4e5a74cc4 --- /dev/null +++ b/09-objekty/trida_op.py @@ -0,0 +1,8 @@ +class Zvire: + def __init__(self, jmeno, zvuk): + self.jmeno = jmeno + self.zvuk = zvuk + + def __eq__(self, other): + return self.jmeno == other.jmeno and \ + self.zvuk == other.zvuk diff --git a/09-objekty/trida_str.py b/09-objekty/trida_str.py new file mode 100644 index 0000000000000000000000000000000000000000..d7742c9deea5bb567beb2d24048a0ad2d04bda66 --- /dev/null +++ b/09-objekty/trida_str.py @@ -0,0 +1,10 @@ +class Zvire: + def __init__(self, jmeno, zvuk): + self.jmeno = jmeno + self.zvuk = zvuk + + def __str__(self): + return self.jmeno + + def __repr__(self): + return f"Pes({self.jmeno}, {self.zvuk})" diff --git a/TODO b/TODO index 6d4b7e13beda62393dc32c6b8d51d74f9bde6674..f6697236b1846bd91dd95bd9cc4546292a8180ea 100644 --- a/TODO +++ b/TODO @@ -5,6 +5,6 @@ - sort(key=...) - funkce vyšších řádů - rekurze -- comprehension pro slovníky a množiny +- životnost objektů, destruktory, weak references - příště u domácích úkolů napsat, jak velké vstupy mají zvládat