5. gyakorlat¶
A gyakorlat anyaga¶
Saját fájlokból modulok¶
- Modulok készítése
- Almodul,
__init__.py
szerepe __init__.py
import, minden importálás, átnevezése- A csillagos import hibájának fixálása
__all__
segítségével
Functools¶
- Órai cache jobban
import functools
from contextlib import contextmanager
import time
# https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)
@functools.lru_cache(50)
# @functools.lru_cache(None)
def factorial(n):
r = 1
i = 2
while i <= n:
r *= i
i += 1
return r
@contextmanager
def timed():
start_time = time.time()
yield
end_time = time.time()
print("Total execution time: {}".format(end_time - start_time))
def main():
with timed():
for i in range(5000):
factorial(3000 + (i % 50))
if __name__ == '__main__':
main()
Cached property¶
import functools
from contextlib import contextmanager
import time
@contextmanager
def timed():
start_time = time.time()
yield
end_time = time.time()
print("Total execution time: {}".format(end_time - start_time))
# def factorial(n):
# return n * factorial(n - 1) if n else 1
def factorial(n):
r = 1
i = 2
while i <= n:
r *= i
i += 1
return r
class SzamStatisztika:
def __init__(self, szam):
self.szam = szam
def jegyek_szama(self):
return len(str(self.szam))
@functools.cached_property
# @property
def faktorialis(self):
return factorial(self.szam)
if __name__ == '__main__':
szam1 = SzamStatisztika(30)
print(szam1.faktorialis)
with timed():
szam2 = SzamStatisztika(80000)
szam2.faktorialis
szam2.faktorialis
Partial¶
import functools
def termek_adatok(kategoria, termek_neve, ar, leiras):
print("Termék neve:", termek_neve)
print("Kategória:", kategoria)
print(f"Ára: {ar} Ft")
print(leiras)
print("---")
termek_adatok("Plüss micimackó", "plüss", 1200, "A legjobb plüss Micimackó")
# Partial, első paraméterek megadása
szamitogep_adatok = functools.partial(termek_adatok, "Szamitogep")
szamitogep_adatok("Acer Predator", 250000, "Nagyon komoly gamer laptop, Minecraft 120 fps!!!")
# Partial, az utolsó paraméterek megadása
leiras_nelkuli_termek = functools.partial(termek_adatok, leiras="Nincs leírás")
leiras_nelkuli_termek("plüss", "Malacka plüss", 1000)
# Partial, első és utolsó paraméterek megadása
szamitogep_leiras_nelkuli_termek = functools.partial(termek_adatok, "Szamitogep", leiras="Nincs leírás")
szamitogep_leiras_nelkuli_termek("Acer Predator", 250000)
Total ordering¶
import functools
@functools.total_ordering
class Teglalap:
def __init__(self, a, b=0):
self.a = a
self.b = (b if b > 0 else a)
def terulet(self):
return self.a * self.b
def kerulet(self):
return 2 * self.a + 2 * self.b
def __eq__(self, other):
if isinstance(other, Teglalap):
return self.terulet() == other.terulet()
return False
def __lt__(self, other):
if isinstance(other, Teglalap):
return self.terulet() < other.terulet()
return False
if __name__ == '__main__':
t1 = Teglalap(6, 5)
print(t1.terulet())
print(t1.kerulet())
t2 = Teglalap(5, 6)
t3 = Teglalap(3, 10)
print("---")
print(t1 == t2)
print(t1 < t2)
print(t1 <= t2)
print(t1 > t2)
print(t1 >= t2)
print(t1 != t2)
print("---")
print(t1 == t3)
print(t1 < t3)
print(t1 <= t3)
print(t1 > t3)
print(t1 >= t3)
print(t1 != t3)
print("---")
t4 = Teglalap(8)
print(t2 > t4)
print(t2 <= t4)
Operációs rendszerrel/Fájlokkal kapcsolatos műveletek¶
import os
import shutil
def main():
print(os.name)
print(os.environ)
print(os.sep)
print(repr(os.linesep))
print("---")
print("Jelenlegi konyvtar", os.getcwd())
print("Fájlok:")
print(os.listdir("."))
print("---")
# Egy könyvtárral felmegyünk
os.chdir("./sajat_mappa")
print("Jelenlegi konyvtar", os.getcwd())
print("Fájlok:")
print(os.listdir("."))
print("---")
for f in os.listdir("."):
print(f)
# Fáj teljes útvonala
print(os.path.abspath(f))
# Fájl relatív útvonala (mindig az aktuális munkakönyvtárhoz viszonyítva)
print(os.path.relpath(f))
# print(os.stat(f))
print(os.stat(f).st_size) # bájt
rossz_utvonal = "abc/asd"
rossz_utvonal2 = r"alma\korte"
# Útvonalak összefűzése (nem kell, hogy létező legyen!)
jo_utvonal = os.path.join("asd", "edasdasdas")
print(jo_utvonal)
# Útvonalak létezőségének ellenőrzése
print("Útvonal létezik?", os.path.exists(os.path.join(jo_utvonal)))
print("Útvonal könyvtár?", os.path.isdir(os.path.join(jo_utvonal)))
print("Útvonal fájl?", os.path.isfile(os.path.join(jo_utvonal)))
# Így nem lehet teljes mappaszerkezetet létrehozni
# Ez megfelel a sima mkdir parancsnak
# os.mkdir(jo_utvonal)
# Vigyázat! Ha létezik a mappa, hibát kapunk!
os.mkdir("cicas_dolgok")
os.mkdir("kutyas_dolgok")
os.makedirs(jo_utvonal)
print("Útvonal létezik?", os.path.exists(os.path.join(jo_utvonal)))
print("Útvonal könyvtár?", os.path.isdir(os.path.join(jo_utvonal)))
# Ez egy könyvtár kitörlésése használható, feltétele, hogy üres legyen a könyvtár
os.rmdir(jo_utvonal)
# print("Útvonal létezik?", os.path.exists(os.path.join(jo_utvonal)))
# os.makedirs(jo_utvonal)
# # Több könyvtár törlésése a removedirs() használható, ez is üres könyvtárakra működik
# os.removedirs(jo_utvonal)
# Fájl másolása
shutil.copy("baby_seal.png", "my_favorite_seal.png")
# Csak viccelek
# 1 darab fájl törlése
os.remove("my_favorite_seal.png")
os.mkdir("seal")
# Másolás átnevezéssel
shutil.copy("baby_seal.png", os.path.join("seal", "my_favorite_seal.png"))
# Fájl másolása egy könyvtárba
shutil.copy("baby_seal.png", "seal")
# A seal mappa már nem üres, így nem is lehet törölni az rmdir paranccsal.
# Workaround: fájl(ok) törlése, mappa törlése
# os.rmdir("seal")
# Az rmtree kitörli a mappát a tartalmával együtt.
shutil.rmtree("seal")
# Bemásoljuk a kedvenc fókánkat
os.mkdir("seal")
# Másolás átnevezéssel
shutil.copy("baby_seal.png", os.path.join("seal", "my_favorite_seal.png"))
# Fájl másolása egy könyvtárba
shutil.copy("baby_seal.png", "seal")
# Teljes mappaszerkezet átmásolása
shutil.copytree("seal", "favorite_selas")
# Fájl/mappa átnevezése
os.rename("favorite_selas", "favorite_seals")
print(os.path.split(os.path.abspath("seal")))
print(os.path.splitdrive(os.path.abspath("seal")))
print(os.path.splitext(os.path.abspath("seal")))
print(os.path.splitext(os.path.abspath("adult_seal.png")))
print(os.path.splitext(os.path.abspath("adult_seal.tar.gz")))
# Fájl név
print(os.path.basename(os.path.abspath("adult_seal.tar.gz")))
# Mappa név
print(os.path.dirname(os.path.abspath("adult_seal.tar.gz")))
if __name__ == '__main__':
main()
Deep copy¶
import copy
weather_szeged = {
'city': 'Szeged',
'temp': 12,
}
weather_budapest = {
'city': 'Budapest',
'temp': 10,
}
weather_forecast_list = [weather_szeged, weather_budapest]
weather_copy = copy.copy(weather_forecast_list)
weather_copy = copy.deepcopy(weather_forecast_list)
weather_copy[0]['city'] = 'Swaged'
print('Eredeti lista', weather_forecast_list)
print('Másolat lista', weather_copy)
print('Eredeti Szegedi időjárás objektum', weather_szeged)
Órai feladatok¶
Megjegyzés
Az órai feladatok alatt lévő feladat(sor)ok azok a feladat(sor)ok, amelyek megoldása beleszámít a zh javításért megoldandó feladatok közé. Ezen feladat(sor)okból 6 darab megoldása szükséges ahhoz, hogy egy zh javíthatóvá váljon. Ha külön nem jelezzük, a teljes feladatsor megoldása esetén jár a zh javításért szerezhető pont.
Info
A teljes feladatsor megoldása szükséges a zh javításért járó pont megszerzéséért.
Mappaváltó context manager¶
Készíts egy context managert, ami a blokkba kerüléskor mappát vált az adott mappára, majd visszatér az eredeti mappához a blokkból való távozáskor.
def change_dir(d):
pass
print(os.getcwd())
with change_dir("../"):
print(os.getcwd())
print(os.getcwd())
Egyszerű statisztika¶
Számoljunk statisztikát fájltípusok (kiterjesztések) szerint. A kiterjesztések nem érzékenyek a kis- és nagybetűkre (jpg és JPG kiterjesztés ugyanaz). Számoljuk meg adott kiterjesztésből hány darab fájl van, mi az összes, átlagos, legkisebb és legnagyobb fájlméret. A függvény egy dictionary objektummal térjen vissza, amelyben a kulcsok a kiterjesztések, és az érték pedig egy másik dictionary, ami tartalmazza az adott mappában lévő adott kiterjesztéshez kapcsolódó adatokat.
Ha egy fájlnak nincs kiterjesztése, akkor kerüljön a nincs
kategóriába.
Ennek visszatérési értéke például:
{
"py": {
"atlagos_fajlmeret": 200,
"min_fajlmeret": 100,
"max_fajlmeret": 300,
"fajlok_szama": 3
},
"json": {
"atlagos_fajlmeret": 4,
"min_fajlmeret": 231,
"max_fajlmeret": 32141,
"fajlok_szama": 23
},
"yaml": {
"atlagos_fajlmeret": 12,
"min_fajlmeret": 231,
"max_fajlmeret": 32141,
"fajlok_szama": 200
},
"xlsx": {
"atlagos_fajlmeret": 3111,
"min_fajlmeret": 3111,
"max_fajlmeret": 3111,
"fajlok_szama": 1
}
}
Okos kiterjesztés levágó¶
Az os.path.splitext
sajnos a legutolsó pont utáni részt vágja csak le, azonban egy fájl "rendes" kiterjesztése az első pont utáni rész végig (pl.: tar.gz
).
Készítsd el a normal_splitext
metódust, ami így vágja le a fájlok kiterjesztését.
A visszatérési értéke egy tuple legyen, amelyben a fájl útvonala szerepel a 0. pozíción, az 1. pozíció pedig a kiterjesztés.
Példa input:
A visszatérési érték ebben az esetben:
Rendezgetés vol. 1¶
Készíts egy függvényt, amely a megadott mappát rendez, és kettébontja a cicás és kutyás dolgokat.
A feladat megoldásához példát adhat a sajat_mappa
, amelynek fájljait rendezhetjük a cicas_dolgok
és kutyas_dolgok
mappába.
A fájlokban nézzük meg, hogy szerepel-e a "cat" vagy "dog" szó, és ezek szerint másoljuk a mappákba.
Amennyiben egy fájlban egyik szó sem szerepel, azzal ne csináljunk semmit.
Rendezgetés vol. 2¶
Egészítsük ki az előző kódot: amennyiben egy fájlban egyik szó sem szerepel, kérdezzük meg a felhasználót, hogy mit szeretnénk kezdeni az adott fájllal:
- Ha a felhasználó azt írja be, hogy "cica" vagy "cat", másoljuk a "cicas_dolgok" mappába, és a fájlt nevezzük át "cica_[index]", az [index] helyére egy folyóindexet tegyünk.
- Ha a felhasználó azt írja be, hogy "kutya" vagy "dog", másoljuk a "kutyas_dolgok" mappába, és a fájlt nevezzük át "kutya_[index]", az [index] helyére egy folyóindexet tegyünk.
- Minden más esetben pedig ne csináljunk semmit az adott fájllal.
Fact generátor¶
Készítsünk két random tényeket visszaadó függvényt. Ehhez olvassuk be soronként a "clean_cat_facts.txt" és "clean_dog_facts.txt" fájlt. Amennyiben nem létezik, hozzuk létre őket. Ehhez olvassuk be soronként a "cat-facts.txt" és "dog_facts.txt" fájlt. A fájlok nagyjából jók, azonban lehetnek benne üres sorok például, ezeket szűrjük ki belőle. Lehetnek a tények előtt sorszámok, ezeket távolítsuk el, majd az így létrejövő sorokból készüljenek el a "clean-" kezdetű fájlok. Amennyiben léteznek a fájlok, olvassuk be őket soronként, és adjunk vissza egy véletlenszerű sort.
Házi feladat¶
Partial method¶
A partial methodok megértése, kipróbálása: https://docs.python.org/3/library/functools.html#functools.partialmethod