From cec1d98510fa8a29b07bca9c491c150a18060928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20L=C3=A1szl=C3=B3?= <rlacko99@gmail.com> Date: Wed, 10 Mar 2021 17:26:16 +0100 Subject: [PATCH] fixed classes chapter --- guide/07_scope_class.md | 238 +++++++++++++++++++++++++++++++++++----- guide/injektalas.svg | 3 + 2 files changed, 214 insertions(+), 27 deletions(-) create mode 100644 guide/injektalas.svg diff --git a/guide/07_scope_class.md b/guide/07_scope_class.md index 9167190..c3625bb 100644 --- a/guide/07_scope_class.md +++ b/guide/07_scope_class.md @@ -16,8 +16,10 @@ - [Python osztály](#python-osztály) - Felépítés, példák, init és dunder metódusok - [Láthatóság](#láthatóság) - \_ -al privátnak tekintjük -- [Öröklés](#öröklés) - Keres a megadott ősosztályokban, - "minden `virtual`" +- [Öröklés](#öröklés) - `Osztály(Ős1, Ős2, ...)`, + Melyik függvényt hívjam? + - [super](#super) - Függvény keresés egy sorrend + alapján </Note> @@ -30,6 +32,9 @@ megtanulni a dolgokat_ - Készíts osztályokat a kutyáknak, macskáknak és a medvéknek úgy, hogy ezeknek legyen ősosztálya és a legtöbb közös tulajdonságot reprezentálja. +- Injektálj be egy osztályt a kutyák és a készített + ősosztály közé úgy, hogy minden konstruktor + lefusson. (Tipp: super) </Note> @@ -37,7 +42,7 @@ megtanulni a dolgokat_ Az osztályok egy lehetőséget biztosítanak, hogy az adatainkat és a hozzájuk kapcsolódó funkcionalitást -össze csatoljuk. +összecsatoljuk. Osztályainkból különböző objektumokat tudunk létrehozni, melyek saját egyedi adatokkal rendelkeznek. Ezek mellett az egyes osztályainknak lehetnek leszármazottaik, @@ -168,12 +173,12 @@ Hogy legyen is benne valami: Ebből tudunk egy példányt készíteni: ```python ->>> x = Osztalyom() +>>> x = Osztalyom() # Példányosítás >>> x.i 12345 ``` -Ilyenkor meghívtuk az alapértelmezett konstruktorát. +Ilyenkor meghívódott az alapértelmezett konstruktora. Ha saját konstruktort szeretnénk, akkor a beépített **\_\_init\_\_** függvényt tudjuk felhasználni. @@ -198,7 +203,7 @@ hívják_ ``` Egy érdekes különbség C-től, hogy a változóinkat -nem definiáljuk kötvetlen, hanem az init metódusában +nem definiáljuk közvetlen, hanem az init metódusában vesszük fel őket. Ha ezt nem így tennénk, akkor valójában egy statikus minden objektum közt megosztott változót készítenénk. @@ -263,9 +268,9 @@ class Dog: Erre a magyarázat, hogy ezekre az objektumokra csak mutatók készülnek. Tehát mikor mi definiáltuk az osztályunk akkor készítettünk -egy új listát `[]`, majd pedig a trickset rámutattuk a +egy új listát `[]`, majd pedig a tricks változót rámutattuk a listánkra. -Ezt követően mikor ebből új objektumokat képeztünk, +Ezt követően mikor ebből új példányokat képeztünk, akkor ugyanazokat a mutató értékeket kapták az egyes leszármazottak. @@ -294,31 +299,210 @@ class Lathatosag: ## Öröklés -Talán az egyik legbonyolultabbnak ható témakör, -viszont Pythonban hidd el, hogy nagyon egyszerűen -működik. +Mikor egy osztályból leöröklünk, akkor a gyerekosztály +megjegyzi az ősét és később tudunk rá hivatkozni. +Az egyes függvények és változók elérhetőek +a leszármazott osztály `self`-jében, viszont hogy +pontosan melyik ősosztály függvényét hívjuk, ha +egyezés van köztük az nem egyértelmű elsőre ha +például több osztályunk is van. + +Nézzük is meg! +(`Osztálynév(Ősosztály, ...)`) ```python -class Osztály(Ősosztály1, Ősosztály2, ...): - . - . - . +class A: + pass + +class B(A): + pass + +b = B() # Példányosítottuk +print(isinstance(b, A)) +# isinstance metódus ellenőrzi, hogy leszármazottja-e +# az objektumunk A-nak + +# Kimenet: +# True +``` + +Akár több osztályt is megadhatunk ősosztálynak. + +Tegyünk bele pár konstruktort + +```python +class A: + def __init__(self): + print("A") + +class B(A): + def __init__(self): + print("B") +``` + +Mit gondolsz, példányosításkor mi fog történni? + +```python +b = B() + +# Kimenet: +# B +``` + +Nem futott le az A konstruktora. +Ezt két féleképp tudjuk megoldani. + +```python +class A: + def __init__(self): + print("A") + +class B(A): + def __init__(self): + A.__init__(self) # Explicit meghívjuk A konstruktorát + print("B") + +b = B() + +# Kimenet: +# A +# B ``` -Ilyenkor az osztályunk elmenti az összes ősosztályát, -majd pedig ha hivatkozni próbálunk benne valamire, -akkor sorban ellenőrzi először az Osztály-ban, majd -pedig az Ősosztályokban, hogy hol található meg. -Ha nem található, akkor meg a szokásos hibával tér vissza. -Tehát C++-ra gondolva például minden függvényünk `virtual`. +### super -Ha szeretnénk az ősosztály konstruktorát meghívni, akkor -a `super` kulcsszót tudjuk használni. +Másik megoldás, hogy használjuk a beépített `super` függvényt. ```python -def __init__(self): - super().__init__() +class A: + def __init__(self): + print("A") + +class B(A): + def __init__(self): + super().__init__() + # ez super(B, self).init() -ként is írhatnánk + # alapértelmezetten az üres verzió python 3-ban + # (B, self)-re egészül + print("B") + +b = B() + +# Kimenet: +# A +# B ``` -Ha többszörös öröklésünk van, akkor sorban mindre -meg fogja hívni az `__init__` függvényt. +A `super` függvény ilyenkor egy úgynevezett +metódus feloldási sorrendet követve végigjárja +a megadott osztálytól kezdve az ősosztályokat +és megkeresi a megfelelő függvényt, majd megáll. +Tehát a fenti példánál megtalálta `A`-ban az +`__init__` függvényt és abbahagyta a keresést, +majd meghívta a függvényt. + +A metódus feloldási sorrendünk ez esetben: + +```python +print(B.__mro__) # Method Resolution Order + +# Kimenet: +# (<class '__main__.B'>, +# <class '__main__.A'>, +# <class 'object'>) +``` + +Mikor a `super`-t alapértelmezetten `B`-től indítottuk, +akkor a következő `A` osztályban kereste meg az `__init__` +függvényt. + +_Azt is észrevehetted, hogy alapértelmezetten az osztályaink +az object osztályból öröklődnek_ + +Na de miért használjak `super` -t? + +```python +class A(object): + def __init__(self): + print('A.__init__(self) -t hívtunk') + +class B(A): + def __init__(self): + print('B.__init__(self) -t hívtunk') + A.__init__(self) # Nem használtam Super-t + +class C(A): + def __init__(self): + print('C.__init__(self) -t hívtunk') + super(C, self).__init__() # Használtam Supert +``` + +Ha netán úgy döntenénk, hogy ezekből az osztályokból +leszeretnénk származni, de úgy, hogy +A alá még helyezünk egy osztályt, így: + +<ImageZoom + src="guide/injektalas.svg" + :border="false" + width="100%" +/> + +```python +class Injektalt_Osztaly(A): + def __init__(self): + print('Injektalt_Osztaly.__init__(self) -t hívtunk') + super(Injektalt_Osztaly, self).__init__() + +class B_bol(B, Injektalt_Osztaly): + pass + +class C_bol(C, Injektalt_Osztaly): + pass + +B_bol() +# Kimenet: +# B.__init__(self) -t hívtunk +# A.__init__(self) -t hívtunk + +C_bol() +# Kimenet: +# C.__init__(self) -t hívtunk +# Injektalt_Osztaly.__init__(self) -t hívtunk +# A.__init__(self) -t hívtunk +``` + +Miért nem futott le a B_bol esetén? +Nézzük meg a metódus feloldási sorrendet + +`<class '__main__.B_bol'>,` +`<class '__main__.B'>,` +`<class '__main__.Injektalt_Osztaly'>,` +`<class '__main__.A'>,` +`<class 'object'>` + +`B_bol` osztály után meghívódott `B` konstruktora, +mert az alapértelmezett konstruktora `B`-nek meghívja +a `super()` függvényt. +Ezt követően `B`-ben a következő hívás `A`-ra fog +mutatni. +Ezt követően pedig a végére érünk és ha hívnánk +újabb `super`-t, akkor már az object jönne. + +Mikor a `C_bol` osztályból indultunk, akkor `C` +osztályban a `super` függvény lefutott és +az `Injektalt_Osztaly`-ban megtalálta a függvényünk. + +<Note type="tip" label> + +<Badge type="tip">Összefoglalva</Badge> +Mikör öröklünk és a super függvényunk használjuk, +akkor felépít egy metódus feloldási sorrendet attól +függően, hogy hogyan definiáltuk az osztályainkat. +Ezt követően mikor hívogatjuk a super-eket, +akkor mindig a sorrendben következő fog jönni, kivéve +ha átugorjuk, mert statikusan definiáljuk, hogy +melyik a következő osztály. + +A super-el akár más függvényeket is megtudunk így találni. + +</Note> diff --git a/guide/injektalas.svg b/guide/injektalas.svg new file mode 100644 index 0000000..762c04a --- /dev/null +++ b/guide/injektalas.svg @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="571px" height="351px" viewBox="-0.5 -0.5 571 351" content="<mxfile host="app.diagrams.net" modified="2021-03-10T15:55:32.730Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36" etag="zjmbRn0q47QHrzn2UEQo" version="14.2.1"><diagram id="8qbvYp1L-6Gzw-SXsElt" name="Page-1">7ZlBc6IwGIZ/Dcc6JCFgj9a2uz3stjMe2t1LJ4VUaJHYGBX76zdIAgR11LaInfWiyZvkI/neh0jQQv1R+oOTcfiLBTS2oB2kFrq0IHQwlJ+ZsMgFz8W5MORRkEugFAbRO1WirdRpFNCJ0VEwFotobIo+SxLqC0MjnLO52e2ZxeZVx2RIV4SBT+JV9T4KRJirXWyX+k8aDUN9ZWCrlhHRnZUwCUnA5hUJXVmozxkTeWmU9mmc5U7nJR93vaG1mBinidhlwG/nJfzri7uzG+/2Pomc2eDNPVPuzEg8VQu2oBvLeBfPTIaVsxYLlQr3bcp0w9lkaVRPdoBonJaNsjTMvns6jJxPHinXVSqKoJCzaRLQbIq2bJ6HkaCDMfGz1rkESmqhGMWyBorRM8oFTTdmARS5lUxSNqKCL2QXDaQGS/GojZyX5npKCiu+ao0onIZF4DLjsqCSvocBqCEDLo7VABebBgCvZQechhzoH6sD4NgcwE3dA49PLNahnnhpwHH6gj3TFwRb9sVt6s74Xr5Ap+YLatkXryFfbpIX+ipILB5vJ+/C6iOrB+LF9zEK1TY2uMYocH5Ip7prnKoliSZBL3tOlbWnmPmvMhUBmYTLtGV5ke3XUXbVZRJlTT0jA2jmj6aReKiU/2QjOljVLlMdIKssimhykQ/LjggCLWQjQcfGnhbKwcuaMfqO8kjminIl5uujwcpTdc1EmQM25T7dvv0IwodUbLsdVqGomu4qgzmNiYhm5tzWua7C3bFoeUPpHdo2AXPsGjj5mtSo6rN4LZDrbgmUL3olkCSFLCrdxlmHyeYJo/pPCjbOCLKQRywJLxL4cejPDw+9/THo3RrywGkZeXxC/rPI1yd8EOT1ofKgzHcgrmK/K/TYgH4L8C1s587/w/aX4QfawO9b0bfrzopO9O1N37qXiEdJX5W9CorN0+fsSB880bc3feveoB7TT+8XYnTAzanmKsCog92PEeJ0zVhdfFhA1r3gbRwQx0XGmUSdLTZvUrJSP1hUj+fd+lml9eO5d9rT9kdWVst//PLu5d+m6Oof</diagram></mxfile>" style="background-color: rgb(255, 255, 255);"><defs/><g><rect x="260" y="0" width="70" height="70" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 35px; margin-left: 261px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 23px">A</font></div></div></div></foreignObject><text x="295" y="39" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">A</text></switch></g><rect x="500" y="120" width="70" height="70" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 155px; margin-left: 501px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 23px">B</font></div></div></div></foreignObject><text x="535" y="159" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">B</text></switch></g><rect x="0" y="120" width="70" height="70" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 155px; margin-left: 1px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 23px">C</font></div></div></div></foreignObject><text x="35" y="159" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">C</text></switch></g><rect x="420" y="270" width="70" height="70" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 305px; margin-left: 421px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 23px">B_bol<br /></font></div></div></div></foreignObject><text x="455" y="309" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">B_bol
</text></switch></g><rect x="90" y="280" width="70" height="70" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 68px; height: 1px; padding-top: 315px; margin-left: 91px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 23px">C_bol<br /></font></div></div></div></foreignObject><text x="125" y="319" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">C_bol
</text></switch></g><rect x="200" y="180" width="190" height="70" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 188px; height: 1px; padding-top: 215px; margin-left: 201px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><font style="font-size: 23px">Injektalt_Osztály<br /></font></div></div></div></foreignObject><text x="295" y="219" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">Injektalt_Osztály
</text></switch></g><path d="M 160 315 L 210.3 302.43 Q 220 300 226.65 292.53 L 251.6 264.53" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 260.25 254.82 L 256.45 268.86 L 246.75 260.21 Z" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 420 305 L 359.97 300.71 Q 350 300 344.08 291.94 L 322.36 262.36" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 314.66 251.88 L 327.6 258.51 L 317.12 266.21 Z" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 107.5 280 L 43.86 200.99" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 35.7 190.87 L 48.92 196.92 L 38.79 205.07 Z" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 455 270 L 525.02 199.98" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 534.21 190.79 L 529.61 204.58 L 520.42 195.39 Z" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 35 120 L 246.79 39.99" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 258.95 35.4 L 249.09 46.07 L 244.5 33.91 Z" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 517.5 120 L 342.86 40.83" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 331.02 35.46 L 345.54 34.91 L 340.17 46.75 Z" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 287.97 180.98 L 287.15 88.11" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 287.03 75.11 L 293.65 88.05 L 280.65 88.17 Z" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg> \ No newline at end of file -- GitLab