NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze – Lekce 10 - Dědičnost a polymorfismus v Pythonu

Zpět

Upozorňujeme, že diskuze pod našimi online kurzy jsou nemoderované a primárně slouží k získávání zpětné vazby pro budoucí vylepšení kurzů. Pro studenty našich rekvalifikačních kurzů nabízíme možnost přímého kontaktu s lektory a studijním referentem pro osobní konzultace a podporu v rámci jejich studia. Toto je exkluzivní služba, která zajišťuje kvalitní a cílenou pomoc v případě jakýchkoli dotazů nebo projektů.

Komentáře
Avatar
Petr Čech
Tvůrce
Avatar
Petr Čech:22.3.2017 17:53

Je sice hezké, že Python umí vícenásobnou dědičnost, ale neumí protected atributy :/ . Musím říct, že OOP v Pythonu mi připadá dost nedokonalé

Odpovědět
22.3.2017 17:53
the cake is a lie
Avatar
Vorlagh
Člen
Avatar
Odpovídá na Petr Čech
Vorlagh:23.3.2017 10:57

Tak python spoleha na inteligenci programatoru v tomhle směru a pripadne dodrzovani konvenci.
Jinak tam moc nevidim potrebu protected atributu. (Ale klidne me oprav, stale se ucim a mozna mi neco unika ;) )

"Raymond Hettinger, a Python core developer, famously put it this way: Python has no locked doors; it's a consenting adults language. If you open the door you're responsible for what you see."

 
Odpovědět
23.3.2017 10:57
Avatar
Petr Čech
Tvůrce
Avatar
Odpovídá na Vorlagh
Petr Čech:23.3.2017 14:45

Tady nejde vůbec o inteligenci programátorů jako spíše o to, že ten jazyk nenabízí něco, co je poměrně standardní. Je jednodušší pracovat s tím, co se tvůrce rozhodl odkrýt pro případné potomky a je bezpečné s tím zacházet.
Protected atribut (ideálně s dalšími klíčovými slovy - třeba C# má virtual) ti říká, že to je něco, co je celkem zbytečné pro použití zvenčí a nemá vůbec smysl se tím navenek zabývat, ale může se to hodit v potomkovi. Uvedu C# příklad:
Máš třídu WebClient, která je skvělá na jednorázové stahování dat. Řekněme, že chceš, aby si pamatovala cookies. Zjistíš, že má protected metodu GetHttpRequest. Ta metoda by byla jako veřejná úplně zbytečná a nemá smysl ji uvádět v intellisense. Ale já vám, že v potomkovi je bezpečné ji přepsat tak, aby se do toho HttpRequestu přidaly ti cookies.
IMHO je špatně otevírat dveře tam, kde to není třeba. Jakožto programátor se nechci hrabat v hotových třídách a zjišťovat, co se rozbije, když změním něco, co není veřejně přístupné. Prostě vím, že když to má takovou úroveň přístupu, neměl bych na to zvenčí sahat. Pokud chci, udělám si potomka, co opět zajistí, že vše bude fungovat, ať objekt modifikuji zvenčí jakkoliv. Pokud to objekt neukazuje veřejně, použiju návrhový vzor wrapper.

Odpovědět
23.3.2017 14:45
the cake is a lie
Avatar
coells
Tvůrce
Avatar
Odpovídá na Petr Čech
coells:23.3.2017 18:58
Musím říct, že OOP v Pythonu mi připadá dost nedokonalé

Jestli jsi zvyklý na C# nebo Javu nebo podobný jazyk, je to docela pochopitelné.
Jenže tyhle jazyky nejsou OOP, jsou to jazyky - mají svůj vlastní přístup, expresivitu a formulaci řešení problémů.
Kdykoliv přecházíš mezi jazyky, budeš na tohle narážet, protože výrazové prostředky jazyků se liší.
OOP naproti tomu je myšlenkový koncept.

Pokud se na to podívám takhle, říkáš jenom "třída v Pythonu mi připadá nedokonalá".
A bylo by super, kdyby existoval alespoň jediný jazyk s dokonalým přístupem k OOP.

Python má svůj přístup i vlastní myšlenkové postupy.
Je Pythonský přístup lepší než C#?
Podle mě je daleko lepší, protože je dynamický, jednodušší a mocnější.
Tím ale nehodlám rozporovat tvoje pocity, už proto, že jsem si tímhle sám prošel - je to o zvyku.

Už tě někdy napadlo, v čem se liší potomek třídy od tříd "venkovních"?
V podstatě v ničem, syntakticky říkáš kompilátoru "jsem velký kluk a vím, co dělám, chci vidět i to [protected], co ostatní nevidí."
Sémanticky implicitně říkáš, že tvoje třída je plně polymorfní k předkovi, což se ale dá vyjádřit i jinak.
Prakticky jenom píšeš méně kódu.

Python funguje jinak - je to dynamický jazyk a dá se toho využít.
Dostaneš objekt, od kterého očekáváš, že bude rozumět určitému rozhraní.
Teď nemluvím o klíčovém slovu interface, pouze o tom, že objekt dokáže přijmout danou zprávu (to je neformální definice rozhraní).
Když ji umí, super, když ne, program spadne.
Takže se nemusíš starat, co je objekt zač, stačí, aby ti rozuměl (to je neformální definice polymorfismu).
K mému vlastnímu překvapení jsem v Pythonu skoro přestal používat dědičnost.
Většinou existuje nějaký jednodušší a hezčí způsob.

Je to podobné, jako když v LISPu ze zvyku používáš for-cyklus a říkáš si, že to LISP moc nezvládl.
V pythonu je také potřeba přemýšlet jinak.

  • rozhraní? k čemu, když zacházení s objektem je z principu polymorfní?
  • protected? k čemu, když je objekt dynamický?
  • dědičnost? je to rozumné, když hierarchie tříd obvykle násobně protáhne kód a k řešení problému přispívá jen vzácně?
  • omezení přístupu? kvalitní dokumentace je mnohem lepší

Protected umí být pěkná mrcha, protože tě postrkuje směrem, kdy začneš přemýšlet, jestli má být funkce private nebo protected.
Tím se přestaneš soustředit na to, co právě děláš, a začneš se rozptyloval budoucími problémy, které skoro nikdy nenastanou.
Tam spadá takové to, "co kdyby to někdo potřeboval", "co kdyby tohle někdo chtěl jinak", "co kdyby..."
Pokud zrovna nenavrhuješ veřejné API pro třetí strany, je to past, do které se snadno padá.

Wrapper porušuje principy OOP.
V C# dostaneš objekt, který "umí" to samé co interní instance, ale nemá stejnou sémantiku.
Jestli to není problém, opravdu potřebuješ wrapper?
Jestli je to problém, tak autor původního kódu snad myslel dostatečně dopředu a definoval rozhraní, které můžeš využít, abys ji explicitně dodefinoval.

Co si z toho odnést?
C, Java, C#, ObjC, LISP, Haskell, Prolog, Python, JS - každý z těch jazyků vyžaduje odlišný přístup a jiné myšlení, i když to na první pohled není nutně vidět.
V každém z těch jazyků přemýšlej jinak, nasbírej zkušenost s novým přístupem a pak se rozhodni, kde se určitá situace řeší lépe?

 
Odpovědět
23.3.2017 18:58
Avatar
Matěj Štolfa:22.5.2019 18:43
class Administrator(Uzivatel):

    def __init__(self, jmeno, heslo, vek, telefonni_cislo):
    super().__init__(jmeno, heslo, vek)
    self.__telefonni_cislo = telefonni_cislo

    def pridej_zvire(self, zvire):
    ...

    def vymaz_zvire(self, zvire):
    ...

    ...

Nemělo by být

super().__init__(jmeno, heslo, vek)

odsazeno?

 
Odpovědět
22.5.2019 18:43
Avatar
Nona Hansel
Člen
Avatar
Odpovídá na Matěj Štolfa
Nona Hansel:5.6.2019 12:34

Mělo by to být odsazeno. A mě to navíc v té formě nefunguje, používám místo toho jen
super().__init__()

 
Odpovědět
5.6.2019 12:34
Avatar
skamos
Člen
Avatar
skamos:21.10.2019 11:33

Ahoj

>>> a = 1
>>> isinstance(a, 1)
True
>>> isinstance(a, "Python")
False
>>> isinstance(a, int)
True
>>> isinstance(a, str)
False

mi nefunguje. Zjistil jsem, že funkce isinstance() se má používat trochu jinak.

isinstance(object,class) Nebo jsem to špatně pochopil z článku výše?
 
Odpovědět
21.10.2019 11:33
Avatar
Odpovídá na skamos
Nina Kubačková:29.7.2022 19:15

Taky mě to hlásí chyby, když postupuji podle návodu.

#!/usr/bin/env python3
a = 1
isinstance(a, 1)
Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    isinstance(a, 1)
TypeError: isinstance() arg 2 must be a type, a tuple of types, or a union
 
Odpovědět
29.7.2022 19:15
Avatar
Jakub Urbánek:26.9.2022 12:48

Velmi, ale opravdu velmi chabě vysvětlené zapouzdření a privátní atributy.

 
Odpovědět
26.9.2022 12:48
Avatar
Adéla Petráková:31.3.2023 9:06

Bylo by dobré vypsat do textu obecnou podobu zápisu dědičnosti: např. class nazev_potomka(na­zev_matky):. Příklad je fajn, ale v popisu textu pod příkladem se informace trochu ztrácí.

 
Odpovědět
31.3.2023 9:06
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 22.