IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

Diskusia – 10. diel - Dedičnosť a polymorfizmus v Pythone

Späť

Upozorňujeme, že diskusie pod našimi online kurzami sú nemoderované a primárne slúžia na získavanie spätnej väzby pre budúce vylepšenie kurzov. Pre študentov našich rekvalifikačných kurzov ponúkame možnosť priameho kontaktu s lektormi a študijným referentom pre osobné konzultácie a podporu v rámci ich štúdia. Toto je exkluzívna služba, ktorá zaisťuje kvalitnú a cielenú pomoc v prípade akýchkoľvek otázok alebo projektov.

Komentáre
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é

Odpovedať
22.3.2017 17:53
the cake is a lie
Avatar
Vorlagh
Člen
Avatar
Odpovedá 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."

 
Odpovedať
23.3.2017 10:57
Avatar
Petr Čech
Tvůrce
Avatar
Odpovedá 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.

Odpovedať
23.3.2017 14:45
the cake is a lie
Avatar
coells
Tvůrce
Avatar
Odpovedá 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?

 
Odpovedať
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?

 
Odpovedať
22.5.2019 18:43
Avatar
Nona Hansel
Člen
Avatar
Odpovedá 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__()

 
Odpovedať
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?
 
Odpovedať
21.10.2019 11:33
Avatar
Odpovedá 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
 
Odpovedať
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.

 
Odpovedať
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í.

Odpovedať
31.3.2023 9:06
Cesta na každou horu se zdolává po kouskách
Robíme čo je v našich silách, aby bola tunajšia diskusia čo najkvalitnejšia. Preto do nej tiež môžu prispievať len registrovaní členovia. Pre zapojenie sa do diskusie sa zaloguj. Ak ešte nemáš účet, zaregistruj sa, je to zadarmo.

Zatiaľ nikto nevložil komentár - buď prvý!