Files
2024-09-21 11:20:44 +02:00

873 lines
19 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## [Objektumorientált programozás](https://docs.python.org/3/tutorial/classes.html), nulladik közelítésben\n",
"\n",
"Az objektumorientált programozás(OOP) olyan programozási módszertan, ahol az egymással kapcsolatban álló programegységek hierarchiájának megtervezése áll a középpontban.\n",
"- A korábban uralkodó procedurális megközelítés a műveletek megalkotására fókuszált.\n",
"- OOP esetén adatokat és az őket kezelő függvényeket egységbezárjuk (encapsulation).\n",
"- Az OOP másik fontos sajátossága az öröklődés (inheritance)."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"10 20\n"
]
}
],
"source": [
"# Példa: téglalap osztály.\n",
"\n",
"class Rectangle:\n",
" def __init__(self, a, b): # konstruktor\n",
" self.a = a\n",
" self.b = b\n",
" \n",
" def calc_area(self): # területszámító metódus definiálása\n",
" return self.a * self.b\n",
"\n",
" def calc_perimeter(self): # kerületszámító metódus definiálása\n",
" return (self.a + self.b) * 2\n",
" \n",
"r1 = Rectangle(10, 20) # téglalap objektum létrehozása\n",
"print(r1.a, r1.b)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"200"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r1.calc_area() # metódus meghívása"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"200"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# A Python a metódushívást a színfalak mögött függvényhívássá alakítja át.\n",
"Rectangle.calc_area(r1)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# ...ez a beépített típusokra is igaz.\n",
"(1).__add__(1)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"int.__add__(1, 1)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"314.1592653589793\n",
"125.66370614359172\n"
]
}
],
"source": [
"# Példa: kör osztály.\n",
"\n",
"import math\n",
"\n",
"class Circle:\n",
" def __init__(self, r): # konstruktor\n",
" self.r = r\n",
" \n",
" def calc_area(self): # területszámító metódus definiálása\n",
" return self.r**2 * math.pi\n",
"\n",
" def calc_perimeter(self): # kerületszámító metódus definiálása\n",
" return 2 * self.r * math.pi\n",
" \n",
"c1 = Circle(10)\n",
"c2 = Circle(20)\n",
"print(c1.calc_area())\n",
"print(c2.calc_perimeter())"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"# A kerület-terület arány kiszámítása téglalapok és körök esetén ugyanúgy történik.\n",
"# Hozzunk létre egy egy síkidom ősosztályt, származtassuk ebből a téglalapot és a kört!\n",
"# A kerület-terület arány számítást az ősosztályba tegyük!\n",
"\n",
"class Shape:\n",
" def calc_pa_ratio(self):\n",
" return self.calc_perimeter() / self.calc_area()\n",
"\n",
"class Rectangle(Shape): # a téglalap a síkidomból származik\n",
" def __init__(self, a, b): # konstruktor\n",
" self.a = a\n",
" self.b = b\n",
" \n",
" def calc_area(self): # területszámító metódus definiálása\n",
" return self.a * self.b\n",
"\n",
" def calc_perimeter(self): # kerületszámító metódus definiálása\n",
" return (self.a + self.b) * 2\n",
"\n",
"class Circle(Shape): # a kör a síkidomból származik\n",
" def __init__(self, r): # konstruktor\n",
" self.r = r\n",
" \n",
" def calc_area(self): # területszámító metódus definiálása\n",
" return self.r**2 * math.pi\n",
"\n",
" def calc_perimeter(self): # kerületszámító metódus definiálása\n",
" return 2 * self.r * math.pi"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.6\n",
"1.6666666666666667\n",
"0.19999999999999998\n"
]
}
],
"source": [
"shapes = [Rectangle(10, 5), Rectangle(2, 3), Circle(10)]\n",
"for s in shapes:\n",
" print(s.calc_pa_ratio())"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"def solve_quadratic(a, b, c):\n",
" '''Solve quadratic equation a*x^2 + b*x + c = 0,\n",
" and return solutions in a list.'''\n",
" \n",
" # diszkrimináns kiszámítása\n",
" d = b**2 - 4 * a * c\n",
"\n",
" # elágazás\n",
" if d > 0: # 2 megoldás\n",
" x1 = (-b + d**0.5) / (2 * a)\n",
" x2 = (-b - d**0.5) / (2 * a)\n",
" return [x1, x2]\n",
" elif d == 0: # 1 megoldás\n",
" return [-b / (2 * a)]\n",
" else:\n",
" return []"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"# Feladat: Készítsünk másodfokú egyenlet megoldó osztályt!\n",
"class QuadraticEquation:\n",
" def __init__(self, a, b, c):\n",
" self.a = a\n",
" self.b = b\n",
" self.c = c\n",
"\n",
" def _calc_d(self):\n",
" return self.b**2 - 4 * self.a * self.c\n",
" \n",
" def nsolutions(self):\n",
" d = self._calc_d()\n",
" if d > 0: return 2\n",
" elif d == 0: return 1\n",
" else: return 0\n",
" \n",
" def solve(self):\n",
" '''Solve quadratic equation a*x^2 + b*x + c = 0,\n",
" and return solutions in a list.'''\n",
" \n",
" a, b, c = self.a, self.b, self.c\n",
"\n",
" # diszkrimináns kiszámítása\n",
" d = self._calc_d()\n",
"\n",
" # elágazás\n",
" if d > 0: # 2 megoldás\n",
" x1 = (-b + d**0.5) / (2 * a)\n",
" x2 = (-b - d**0.5) / (2 * a)\n",
" return [x1, x2]\n",
" elif d == 0: # 1 megoldás\n",
" return [-b / (2 * a)]\n",
" else:\n",
" return []"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[-1.0, -2.0]"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"QuadraticEquation(1, 3, 2).solve()"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[-1.0]"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"QuadraticEquation(1, 2, 1).solve()"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[]"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"QuadraticEquation(1, 1, 3).solve()"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2\n",
"[-1.0, -2.0]\n"
]
}
],
"source": [
"eq = QuadraticEquation(1, 3, 2)\n",
"print(eq.nsolutions())\n",
"print(eq.solve())"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"# Feladat: \"Éhes kutyák\".\n",
"\n",
"class Dog:\n",
" def __init__(self, name, is_hungry=False):\n",
" self.name = name\n",
" self.is_hungry = is_hungry\n",
"\n",
" def eat(self):\n",
" self.is_hungry = False\n",
" \n",
"dogs = [\n",
" Dog('Borzas', True),\n",
" Dog('Vadász', False),\n",
" Dog('Nokedli'),\n",
" Dog('Cézár', True),\n",
" Dog('Csibész', True)\n",
"]"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Borzas\n",
"Cézár\n",
"Csibész\n"
]
}
],
"source": [
"# Nézzük meg, hogy kik éhesek!\n",
"for d in dogs:\n",
" if d.is_hungry:\n",
" print(d.name)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"# Etessük meg az összes éhes kutyát!\n",
"for d in dogs:\n",
" if d.is_hungry:\n",
" d.eat()"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Borzas False\n",
"Vadász False\n",
"Nokedli False\n",
"Cézár False\n",
"Csibész False\n"
]
}
],
"source": [
"# Nézzük meg, hogy mi az etetés eredmény!\n",
"for d in dogs:\n",
" print(d.name, d.is_hungry)"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"# Éhezzenek meg a kutyák!\n",
"for d in dogs:\n",
" d.is_hungry = True"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Borzas\n",
"Vadász\n",
"Nokedli\n",
"Cézár\n",
"Csibész\n"
]
}
],
"source": [
"# Újra nézzük meg, hogy kik éhesek!\n",
"for d in dogs:\n",
" if d.is_hungry:\n",
" print(d.name)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Borzas\n",
"Cézár\n",
"Csibész\n"
]
}
],
"source": [
"# Oldjuk meg az \"éhes kutyák\" feladatot osztályok használata nélkül!\n",
"dogs = [\n",
" {'name': 'Borzas', 'is_hungry': True},\n",
" {'name': 'Vadász', 'is_hungry': False},\n",
" {'name': 'Nokedli', 'is_hungry': False},\n",
" {'name': 'Cézár', 'is_hungry': True},\n",
" {'name': 'Csibész', 'is_hungry': True}\n",
"]\n",
"\n",
"for d in dogs:\n",
" if d['is_hungry']:\n",
" print(d['name'])\n",
" \n",
"# ..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Speciális (\"dunder\") [attribútumok](https://docs.python.org/3/reference/datamodel.html#the-standard-type-hierarchy) és [metódusok](https://docs.python.org/3/reference/datamodel.html#special-method-names)\n",
"\n",
"- `__doc__`, `__class__`, `__init__()`, `__hash__()`, `__code__`, ...\n",
"- attribútumtárolásra: `__dict__`, `__dir__()`\n",
"- kiírásra: `__repr__()`, `__str__()`\n",
"- műveletvégzésre: `__add__()`, `__mul__()`, ...\n",
"- indexelésre: `__getitem__()`, `__setitem__()`, `__len__()`\n",
"- iterálásra: `__iter__()`, `__next__()`\n",
"- kontextuskezelésre: `__enter__()`, `__exit__()`\n",
"- ..."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"# Példa: __repr__ metódussal rendelkező osztály.\n",
"class Student:\n",
" def __init__(self, name, neptun):\n",
" self.name = name\n",
" self.neptun = neptun\n",
" \n",
" def __repr__(self):\n",
" return f\"Student('{self.name}', '{self.neptun}')\""
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Student('Gipsz Jakab', 'ABC123')"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Student('Gipsz Jakab', 'ABC123')"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[10, 20, 30]\n"
]
}
],
"source": [
"# A __repr__ metódus a beépített osztályokra is meg van valósítva.\n",
"l = [10, 20, 30]\n",
"print(l.__repr__())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Gyakorlás\n",
"\n",
"Készítsünk vektor osztályt, amely támogatja a vektorok közötti elemenkénti alapműveleteket (+, -, *, /), a vektor elemszámának lekérdezését, a haladó indexelést valamint a vektor sztringgé alakítását! Elvárt működés:\n",
"```\n",
"v1 = Vector([1.0, 2.0, 3.0])\n",
"v2 = Vector([4.0, 5.0, 6.0])\n",
"print(len(v1), v1[0], v1[:2]) # => 3 1.0 [1.0, 2.0]\n",
"print(v1 + v2) # => Vector([5.0, 7.0, 9.0])\n",
"print(v1 * v2) # => Vector([4.0, 10.0, 18.0]\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
"class Vector:\n",
" def __init__(self, data):\n",
" self.data = data\n",
" \n",
" def __repr__(self):\n",
" return f'Vector({str(self.data)})'\n",
" \n",
" def __add__(self, other):\n",
" return Vector([x + y for x, y in zip(self.data, other.data)])\n",
"\n",
" def __sub__(self, other):\n",
" return Vector([x - y for x, y in zip(self.data, other.data)])\n",
"\n",
" def __mul__(self, other):\n",
" return Vector([x * y for x, y in zip(self.data, other.data)])\n",
"\n",
" def __truediv__(self, other):\n",
" return Vector([x / y for x, y in zip(self.data, other.data)])\n",
" \n",
" def __len__(self):\n",
" return len(self.data)\n",
" \n",
" def __getitem__(self, idx):\n",
" return self.data[idx]"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [],
"source": [
"# 2 vektor létrehozása\n",
"v1 = Vector([1.0, 2.0, 3.0])\n",
"v2 = Vector([4.0, 5.0, 6.0])"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Vector([1.0, 2.0, 3.0])"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v1"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Vector([5.0, 7.0, 9.0])"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# műveletek\n",
"v1 + v2"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Vector([-3.0, -3.0, -3.0])"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v1 - v2"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Vector([4.0, 10.0, 18.0])"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v1 * v2"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Vector([0.25, 0.4, 0.5])"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v1 / v2"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# elemszám lekérdezés\n",
"len(v1)"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1.0"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# indexelés\n",
"v1[0]"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1.0, 2.0]"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# haladó indexelés\n",
"v1[:2]"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Vector([5.0, 7.0, 9.0])"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# A műveletek a háttérben egyszerű függvényhívássá alakulnak át.\n",
"v1 + v2"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Vector([5.0, 7.0, 9.0])"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Vector.__add__(v1, v2)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.11.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}