Kihagyás

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.

def stats(a_directory):
    pass

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.

def normal_splitext(f):
    pass

Példa input:

normal_splitext("../alma/korte.szilva/./kiscica/szilvasbukta.2.tar.gz.zip")

A visszatérési érték ebben az esetben:

("../alma/korte.szilva/./kiscica/szilvasbukta", ".2.tar.gz.zip")

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

Kapcsolódó linkek


Utolsó frissítés: 2023-02-21 16:21:41