{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Matematikai Algoritmusok és Felfedezések I.\n", "\n", "## 4. Előadás: Comprehensions, Objektum orientált programozás\n", "### 2022 március 3." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## List comprehension\n", "\n", "- Flat is better than nested.\n", "- Rövidités a foor loop leggyakoribb használatára, hogy gyorsan tudjunk listákat létrehozni" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lista = []\n", "for i in range(10):\n", " lista.append(2*i+1)\n", "lista" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Egy soros megfelelő:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lista = [2*i+1 for i in range(10)]\n", "lista" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Az általános formula \n", "\n", "~~~\n", "[ for in ]\n", "~~~" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 4, 16, 36, 64, 100, 144, 196, 256, 324]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "even = [n*n for n in range(20) if n % 2 == 0]\n", "even" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ami azzal ekvivalens, hogy" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "even = []\n", "for n in range(20):\n", " if n % 2 == 0:\n", " even.append(n)\n", "even" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "egy feltételt is megadhatunk, hogy szűrjük az elemeket:\n", "\n", "~~~\n", "[ for in if ]\n", "~~~\n", "- mivel itt szűrésre használjuk az `if` részt, nincs `else` ág\n", "\n", "- viszont a kezdeti kifejezésben használhatunk esetszétválasztást:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 0, -1, 1, -1, -1, 0]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l = [1, 0, -2, 3, -1, -5, 0]\n", "\n", "signum_l = [int(n / abs(n)) if n != 0 else 0 for n in l]\n", "signum_l" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ez persze nem a list comprehension extrája, hanem csak annyi, hogy ez is egy értelmes kifejezés:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "-1" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "n = -3.2 \n", "int(n / abs(n)) if n != 0 else 0 " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Több listán is végigfuthatunk:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "lista1 = [1, 2, 3]\n", "lista2 = [4, 5, 6]\n", "\n", "[(i, j) for i in lista1 for j in lista2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Egymásba is ágyazhatjuk őket:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[[1, 4, 9], [25, 36, 49]]" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "matrix = [\n", " [1, 2, 3], \n", " [5, 6, 7]\n", "]\n", "\n", "[[e*e for e in row] for row in matrix]" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Set és dictionary comprehension\n", "\n", "Minden analóg módon működik:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(set, 3, {'Apple', 'Pear', 'Plum'})" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fruit_list = [\"apple\", \"plum\", \"apple\", \"pear\"]\n", "\n", "fruits = {fruit.title() for fruit in fruit_list}\n", "\n", "type(fruits), len(fruits), fruits" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(dict, 3, {'apple': 5, 'plum': 4, 'pear': 4})" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "word_list = [\"apple\", \"plum\", \"pear\"]\n", "word_length = {word: len(word) for word in word_list}\n", "type(word_length), len(word_length), word_length" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Vajon mi történik?" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'a': 'avocado', 'p': 'pear'}" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "word_list = [\"apple\", \"plum\", \"pear\", \"avocado\"]\n", "first_letters = {word[0]: word for word in word_list}\n", "first_letters" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Függvények fura viselkedése" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2, 3]\n" ] } ], "source": [ "def furcsafuggveny(l):\n", " k = []\n", " l = k\n", "l = [1,2,3]\n", "furcsafuggveny(l) \n", "print(l)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2, 3, 4, 5]\n" ] } ], "source": [ "def furcsafuggveny2(l):\n", " l.append(4)\n", " l += [5]\n", " l = l + [6]\n", " l.append(7)\n", "l = [1,2,3]\n", "furcsafuggveny2(l)\n", "print(l)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5\n" ] } ], "source": [ "a=5\n", "def foo():\n", " print(a)\n", "foo()" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "ename": "UnboundLocalError", "evalue": "local variable 'a' referenced before assignment", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mUnboundLocalError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[0ma\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m+\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 4\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 5\u001b[1;33m \u001b[0mfoo\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;32m\u001b[0m in \u001b[0;36mfoo\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0ma\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m5\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mfoo\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0ma\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m+\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 4\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[0mfoo\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", "\u001b[1;31mUnboundLocalError\u001b[0m: local variable 'a' referenced before assignment" ] } ], "source": [ "a=5\n", "def foo():\n", " a=a+1\n", " print(a)\n", "foo()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Namespace (névtér)\n", " A namespace a változó nevek és az objektumok közti leképezés (pont mint egy dictionary). \n", " Pl:\n", " - Beépített nevekhez (`abs()`, `sorted()`, `int` stb...) tartozik egy namespace. \n", " - Globális namespace: ide kerülnek a függvényeken kívül létrehozott változók.\n", " - Lokális namespece: minden függvény létrehoz egy saját namespacet, először abban keres. \n", " \n", " Különböző namespacekben szerepelhet egyező név! " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "# Ez egy szándékosan zavaróan megírt kód. \n", "a=5 # a globális namespaceben 'a' az 5-re fog mutatni\n", "def foo(a): # ez már egy másik `a`, ami a foo() függvény namespaceben él\n", " print(a+1) # itt a foo()-hoz tartozó 'a'-ra hivatkozunk. \n", " def belsofugveny(a): # ez egy harmadik 'a' változó, ez már a belsofugveny()-hez tartozik\n", " print(a+5); # itt a belsofugveny()-hez tartozó 'a'-ra hivatkozunk. \n", " belsofugveny(a) # itt a foo()-hoz tartozó 'a'-ra hivatkozunk. \n", " \n", "foo(10)\n", "a # itt a globális 'a'-ra hivatkozunk. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Scope\n", "Minden namespacehez tartozik egy scope. A scope a kódnak az a része, ahol a neveket automatikusan abban az adott namespaceben keresi a program." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "11\n", "15\n" ] }, { "data": { "text/plain": [ "5" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a=5 #\n", " #\n", "def foo(a): # \n", " print(a+1) # \n", " # \n", " def belsofugveny(a): # \n", " print(a+5); #\n", " #\n", " belsofugveny(a) # \n", " #\n", "foo(10) # \n", "a # " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Hogyan érjük el egy másik namespaceben lévő objektumokat?\n", " - a python kifelé keres, először a legbelső namespaceben\n", " - `nonlocal valnev` megmondja, hogy eggyel kintebbi scopeban keressen. (Pontosabban, a \"legutóbbi\" nem lokális használatot keresi)\n", " - `global valnev` megmondja, hogy a globális scopeban keressen. " ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "lokális értékadás után: test spam\n", "nonlocal kulcsszó után: nonlocal spam\n", "global kulcsszó után: nonlocal spam\n", "globális scopeban: global spam\n" ] } ], "source": [ "def scope_test():\n", " def do_local():\n", " spam = \"local spam\"\n", "\n", " def do_nonlocal():\n", " nonlocal spam\n", " spam = \"nonlocal spam\" \n", "\n", " def do_global():\n", " global spam\n", " spam = \"global spam\"\n", "\n", " spam = \"test spam\"\n", " do_local()\n", " print(\"lokális értékadás után:\", spam)\n", " do_nonlocal()\n", " print(\"nonlocal kulcsszó után:\", spam)\n", " do_global()\n", " print(\"global kulcsszó után:\", spam)\n", "\n", "scope_test()\n", "print(\"globális scopeban:\", spam)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "A másik lehetőség, hogy megadjuk, hogy melyik namespaceben kell keresni. " ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3.141592653589793" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import math\n", "math.pi # a math modul namespaceben keresi a pi nevű változót" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Programozási paradigmák\n", "Sokféle van, például:\n", " - Procedurális\n", " - Funckionális\n", " - Objektumorientált \n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Példa: Főzés vs matek vs autók" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mikor melyiket válasszuk? " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Python\n", " - Többféle stílusban is lehet használni, a fentiek mindegyikét tudja többé kevésbé.\n", " - Sokszor vegyesen is használjuk.\n", " - Erősen támogatja az objektumorientált paradigmát. Minden objektum! \n", " " ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[int,\n", " bool,\n", " ,\n", " ]" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# minden objektum\n", "import random\n", "def foo():\n", " pass\n", "[int,bool,foo,random] " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Objektumorientált programozás\n", "\n", "- Osztályok: A programot objektumok köré szervezzük. Minden objektum tartalmaz adatokat és metódusokat, amik az adatokat kezelik. \n", "- Öröklődés (Inheritance): Specifikusabb objektumokat hozhatunk létre, melyek öröklik a korábbiak tulajdonságait\n", "- Egységbezárás (Encapsulation): Az összetartozó adatokat és metódusokat együtt kezeljük. \n", "- Absztrakció (Abstraction): A belső működést elrejtjük és csak a szükséges részt mutatjuk meg a felhasználónak. \n", "- Polimorfizmus (Polymorphism): A leszármazottak és példányok felülírhatják a metódusokat. Több osztályból is örököltethetünk egyszerre. " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Objektum orientáltság Pythonban\n", "https://docs.python.org/3/tutorial/classes.html\n", "### Osztály (class) definiálása\n", "\n", "- `class` kulcsszóval adjuk meg.\n", "- Példányokat tudunk létrehozni\n", "- Minden példánynak van egy saját namespace-e! \n", "- Attribútumokat tudunk kapcsolni hozzájuk melyek nem befolyásolják a többi példány attribútumait.\n", "\n" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "class Ember:\n", " pass" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Gipsz Jakab 24\n", "Gipsz Jakabné 22\n", "Mezga Aladár 23\n" ] } ], "source": [ "a=Ember()\n", "print(type(a))\n", "a.nev=\"Gipsz Jakab\"\n", "a.kor=24\n", "b=Ember()\n", "b.nev=\"Gipsz Jakabné\"\n", "b.kor=22\n", "c=Ember()\n", "c.nev=\"Mezga Aladár\"\n", "c.kor=23\n", "l=[a,b,c]\n", "for e in l:\n", " print(e.nev,e.kor)\n" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "__main__.Ember" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(a)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### Init\n", "- `__init__` függvény automatikusan meghívódik amikor a példány elkészül. \n", " - olyasmi mint egy konstruktor\n", " - nem kötelező\n", "- Minden metódus első paramétere maga a példány. A konvenció, hogy ezt `self`-nek hívjuk. " ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "class Ember:\n", " def __init__(self,nevasd,kor):\n", " print(\"Létrejött egy ember\")\n", " self.kor = kor\n", " self.nev = nevasd\n", " " ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Létrejött egy ember\n", "Létrejött egy ember\n", "Gipsz Jakab 24\n", "Gipsz Jakabné 22\n" ] } ], "source": [ "a=Ember(\"Gipsz Jakab\",24)\n", "b=Ember(\"Gipsz Jakabné\",22)\n", "\n", "l=[a,b]\n", "for e in l:\n", " print(e.nev,e.kor)\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Metódusok\n", "\n", "- Függvények az osztály definíciójában\n", "- Automatikusan az első argumentumuk a példány lesz. " ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1998\n", "False\n" ] } ], "source": [ "class Ember:\n", " def __init__(self,nev,kor):\n", " self.kor = kor\n", " self.nev = nev\n", " \n", " def szuletesi_ev(self): # egy paramétert vár\n", " print(2022-self.kor)\n", " \n", " def egykoru(self,other): \n", " print(self.kor==other.kor)\n", " \n", " \n", "a=Ember(\"Gipsz Jakab\",24)\n", "a.szuletesi_ev() # de paraméter nélkül hívjuk meg, mivel az első paraméter maga 'a' lesz \n", "b=Ember(\"Gipsz Jakabné\",22)\n", "a.egykoru(b)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Metódusok meghívása\n", "Két lehetőség van:\n", "\n", "1. `példány.metódus(param)`\n", "2. `class.metódus(példány, param)`" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1998\n", "1998\n" ] } ], "source": [ "a=Ember(\"Gipsz Jakab\",24)\n", "a.szuletesi_ev() \n", "Ember.szuletesi_ev(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### `__str__` metódus\n", "Egy speciális metódus, amit arra használunk hogy megadjuk, hogy a `print()` függvény hogyan írja ki az objektumot. \n", "\n" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "<__main__.Ember object at 0x000001B81C7A9D48>\n", "(1+4j)\n" ] } ], "source": [ "print(a)\n", "print(1+4j)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gipsz Jakab egy 24 éves budapesti lakos.\n", "Gipsz Jakabné egy 22 éves kecskeméti lakos.\n" ] } ], "source": [ "class Ember:\n", " def __init__(self,nev,kor,lakohely):\n", " self.kor = kor\n", " self.nev = nev\n", " self.lakohely = lakohely\n", " def __str__(self): \n", " return self.nev+\" egy \"+str(self.kor)+\" éves \"+ self.lakohely + \"i lakos.\"\n", " \n", "a=Ember(\"Gipsz Jakab\",24,\"budapest\")\n", "print(a)\n", "b=Ember(\"Gipsz Jakabné\",22,\"kecskemét\")\n", "print(b)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "source": [ "### Osztály attribútumok \n", "\n", "- Olyan attribútum, amin az ossztály összes tagja osztozik. \n" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [], "source": [ "class Ember:\n", " letszam = 42" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "#### A példányokon és a class objektumon keresztül is elérjük" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "42" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = Ember()\n", "a.letszam" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "42" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Ember.letszam" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "#### Megváltoztatni a classon keresztül lehet" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "42 42\n" ] }, { "data": { "text/plain": [ "(43, 42)" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a1 = Ember()\n", "a2 = Ember()\n", "\n", "print(a1.letszam,a2.letszam)\n", "a1.letszam = 43\n", "a1.letszam, a2.letszam" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "#### A példányokon keresztül viszont nem" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(11, 42)" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a1 = Ember()\n", "a2 = Ember()\n", "\n", "a1.letszam = 11\n", "a1.letszam , a2.letszam\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Azért, mert ez egy új attribútumot hoz létre a példány namespacében. " ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "11" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a1.letszam" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Öröklődés\n" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "False\n", "True\n", "False\n", "True\n" ] } ], "source": [ "class Ember:\n", " pass\n", " \n", "class Matematikus(Ember):\n", " pass\n", "\n", "e = Ember() \n", "m = Matematikus()\n", "print(isinstance(e, Matematikus))\n", "print(isinstance(m, Ember))\n", "print(issubclass(Ember, Matematikus))\n", "print(issubclass(Matematikus,Ember))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ha nem írunk semmilyen osztályt, automatikusan az `object` osztály a szülő osztály:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [], "source": [ "o=object()" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "True\n", "True\n" ] } ], "source": [ "class A: pass\n", "class B(object): pass\n", "\n", "print(issubclass(A, object))\n", "print(issubclass(B, object))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Metódus öröklődés\n", "\n", "A metódusok öröklődnek, de felülírhatóak." ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "B.foo függvény\n", "A.bar függvény\n" ] } ], "source": [ "class A(object):\n", " def foo(self):\n", " print(\"A.foo függvény\")\n", " \n", " def bar(self):\n", " print(\"A.bar függvény\")\n", " \n", "class B(A):\n", " def foo(self):\n", " print(\"B.foo függvény\")\n", " \n", "b = B()\n", "b.foo()\n", "b.bar()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Attribútum öröklődés\n", "Mivel az adat attribútumok bárhol létrehozhatóak, csak akkor \"öröklődnek\", ha a szülő osztályban lévő kód meghívódik." ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "b {}\n", "a {}\n", "a {'value': 42}\n", "b {}\n", "b {'value': 42}\n" ] } ], "source": [ "class A(object):\n", " \n", " def foo(self):\n", " self.value = 42\n", " \n", "class B(A):\n", " pass\n", "\n", "b = B()\n", "print('b',b.__dict__) # a __dict__ kiírja az összes attribútumot \n", "a = A()\n", "print('a',a.__dict__)\n", "\n", "a.foo()\n", "print('a',a.__dict__)\n", "print('b',b.__dict__)\n", "\n", "b.foo()\n", "print('b',b.__dict__)\n" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['__class__',\n", " '__delattr__',\n", " '__dict__',\n", " '__dir__',\n", " '__doc__',\n", " '__eq__',\n", " '__format__',\n", " '__ge__',\n", " '__getattribute__',\n", " '__gt__',\n", " '__hash__',\n", " '__init__',\n", " '__init_subclass__',\n", " '__le__',\n", " '__lt__',\n", " '__module__',\n", " '__ne__',\n", " '__new__',\n", " '__reduce__',\n", " '__reduce_ex__',\n", " '__repr__',\n", " '__setattr__',\n", " '__sizeof__',\n", " '__str__',\n", " '__subclasshook__',\n", " '__weakref__',\n", " 'foo',\n", " 'value']" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dir(a)" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'value': 42}" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.__dict__" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### A szülő osztály konstruktora\n", "\n", "- meghívódik az szülő osztály `__init__` függvénye. Viszont mivel az `__init__` nem egy szokásos konstruktor, így nem hívódik meg automatikusan a szülő osztály init függvénye, ha felülírja a gyerek osztály." ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "B.__init__ called\n", "c létrehozása\n", "A.__init__ called\n" ] } ], "source": [ "class A(object):\n", " def __init__(self):\n", " print(\"A.__init__ called\")\n", " \n", "class B(A):\n", " #pass\n", " def __init__(self):\n", " print(\"B.__init__ called\")\n", " \n", "class C(A):\n", " pass\n", " \n", "b = B()\n", "print(\"c létrehozása\")\n", "c = C()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "A szülő osztály metódusai kétféleképpen is elérhetőek\n", "1. a már tanult módon, az osztály nevével\n", "2. vagy pedig a **super** függvény segítségével" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "slideshow": { "slide_type": "-" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "B\n", "A.__init__ \n", "B.__init__ \n", "C\n", "A.__init__ \n", "C.__init__ \n" ] } ], "source": [ "class A(object):\n", " def __init__(self):\n", " print(\"A.__init__ \")\n", " \n", " \n", "class B(A):\n", " def __init__(self):\n", " A.__init__(self)\n", " print(\"B.__init__ \")\n", " \n", "class C(A):\n", " def __init__(self):\n", " super().__init__()\n", " print(\"C.__init__ \")\n", " \n", "print(\"B\")\n", "b = B()\n", "print(\"C\")\n", "c = C()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### 1. Példa: polinomok" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [], "source": [ "class Polinom:\n", " \n", " def __init__(self, lista):\n", " self.ehlista=lista \n", " \n", " def __str__(self):\n", " szoveg=\"\"\n", " for i,eh in enumerate(self.ehlista):\n", " szoveg=szoveg+str(eh)+\"x^\"+str(i)+\"+\"\n", " szoveg=szoveg.rstrip(\"+\") \n", " return szoveg\n", " \n", " def deri(self):\n", " l=[]\n", " for i,eh in enumerate(self.ehlista):\n", " if i==0:\n", " pass\n", " else:\n", " l.append(i*eh)\n", " return Polinom(l)" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1x^0+2x^1+4x^2+5x^3\n", "8x^0+30x^1\n" ] } ], "source": [ "a=Polinom([1,2,4,5])\n", "print(a)\n", "print(a.deri().deri())" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [], "source": [ "class Masodfoku(Polinom):\n", " def egyikgyok(self):\n", " a=self.ehlista[2]\n", " b=self.ehlista[1]\n", " c=self.ehlista[0]\n", " return (-b+(b**2-4*a*c)**(1/2))/(2*a) " ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2x^0+3x^1+1x^2\n", "3x^0+2x^1\n" ] } ], "source": [ "p=Masodfoku([2,3,1])\n", "print(p)\n", "p.egyikgyok()\n", "print(p.deri())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2x^1+1x^0 11\n", "2x^0\n", "(2.220446049250313e-16+1.1102230246251565e-16j)\n", "4x^1+2x^0\n", "3x^2+3x^1+3x^0\n" ] } ], "source": [ "# for ciklusok nélkül is meg tudjuk oldani :)\n", "class Polinom:\n", " \n", " def __init__(self, lista):\n", " self.ehlista=lista\n", " \n", " def __str__(self):\n", " szoveg=\"\".join([str(eh)+\"x^\"+str(i)+\"+\" for i,eh in enumerate(self.ehlista)][::-1])\n", " szoveg=szoveg.rstrip(\"+\") \n", " return szoveg\n", " \n", " def deri(self): \n", " l=[i*eh for i,eh in enumerate(self.ehlista) if i!=0]\n", " return Polinom(l)\n", " \n", " def beh(self,x):\n", " valasz=sum([eh*x**i for i,eh in enumerate(self.ehlista)])\n", " return valasz\n", " \n", " def __add__(self, other):\n", " \n", " l=max(len(self.ehlista),len(other.ehlista))\n", " bovitett_eh1=self.ehlista + [0]*(l - len(self.ehlista))\n", " bovitett_eh2=other.ehlista + [0]*(l - len(other.ehlista))\n", " \n", " uj_ehlista=[bovitett_eh1[i]+bovitett_eh2[i] for i in range(l) ]\n", " \n", " return Polinom( uj_ehlista )\n", " \n", "class Masodfoku(Polinom):\n", " def egyikgyok(self):\n", " a=self.ehlista[2]\n", " b=self.ehlista[1]\n", " c=self.ehlista[0]\n", " return (-b+(b**2-4*a*c)**(1/2))/(2*a) \n", " \n", "p=Polinom([1,2])\n", "print(p,p.beh(5))\n", "print(p.deri())\n", "\n", "m=Masodfoku([1,2,7])\n", "print(m.beh(m.egyikgyok()))\n", "print(p+p)\n", "print(Polinom([1,2,3])+Polinom([2,1]))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### 2. Példa: Sárkányok\n", "![sarkany](dragon.jpg) " ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [], "source": [ "class sarkany:\n", " def __init__(self, nev):\n", " self.nev=nev" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [], "source": [ "class repulo_sarkany(sarkany):\n", " def __init__(self, nev, szarnyfesztav):\n", " super().__init__(nev)\n", " self.szarnyfesztav=szarnyfesztav\n", " \n", " def tamadas(self):\n", " print(\"A\", self.nev, \"nevű sárkány a levegőből rád vetette magát\", )\n", " \n", " def repules(self):\n", " print(\"A\", self.nev, \"nevű sárkány repül\", )\n", " " ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A Smaug nevű sárkány repül\n", "A Smaug nevű sárkány a levegőből rád vetette magát\n" ] }, { "data": { "text/plain": [ "12" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "smaug=repulo_sarkany(\"Smaug\",12)\n", "smaug.repules()\n", "smaug.tamadas()\n", "smaug.szarnyfesztav" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [], "source": [ "class tuzokado_sarkany(sarkany):\n", " def __init__(self, nev):\n", " super().__init__(nev)\n", " \n", " def tamadas(self):\n", " print(\"A\", self.nev, \"nevű sárkány szénné égetett\", )\n", " \n", " def tuzokadas(self):\n", " print(\"A\", self.nev, \"nevű sárkány a tüzet okád\", )\n", " " ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A Süsü nevű sárkány a tüzet okád\n", "A Süsü nevű sárkány szénné égetett\n" ] } ], "source": [ "susu=tuzokado_sarkany(\"Süsü\")\n", "susu.tuzokadas()\n", "susu.tamadas()" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Többszörös öröklődés\n", "- mindegyik osztály metódusai öröklődnek" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [], "source": [ "class repulo_tuzokado_sarkany(repulo_sarkany,tuzokado_sarkany):\n", " def __init__(self, nev, szarnyfesztav):\n", " self.nev=nev \n", " self.szarnyfesztav=szarnyfesztav\n", " \n", " def tamadas(self):\n", " tuzokado_sarkany.tamadas(self)\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Vajon mi lesz az eredmény?" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A Viserion nevű sárkány repül\n", "A Viserion nevű sárkány a tüzet okád\n", "A Viserion nevű sárkány szénné égetett\n" ] } ], "source": [ "viserion=repulo_tuzokado_sarkany(\"Viserion\",25)\n", "viserion.repules()\n", "viserion.tuzokadas()\n", "viserion.tamadas()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Azt, hogy melyik hívódik meg, az MRO (Method Resolution Order) határozza meg. Ez egy sorrend az osztályokon, és egy metódus hívásnál addig megy a sorrendben még meg nem találja valamelyik osztályban a metódust. Nem pontosan így működik, de ökölszabálynak jó, hogy felfelé mélységi kersést végez, balról jobbra sorrendben. \n" ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.4" } }, "nbformat": 4, "nbformat_minor": 5 }