Kihagyás

4. gyakorlat

Warning

Figyelem! A héten kiadásra kerül a második beadandó, 8 pontért! Bővebb információ CooSpace-en.

A gyakorlat anyaga

Dátumok kezelése

A datetime modul néhány részét nézzük meg az órán, azonban mindenkit arra bíztatunk, hogy nyugodtan fedezze fel a modulban rejlő egyéb lehetőségeket is: https://docs.python.org/3/library/datetime.html

Dátum objektumok

A dátumok a datetime modul date osztályában találhatóak. Létrehozása: datetime.date(év, hónap, nap).

Ezekhez tartozó fontosabb metódusok és attribútumok:

Metódus Leírás
today() visszaadja a mai napot date objektumként
fromisoformat() paraméterként egy string-et vár (YYYY-MM-DD alakban), és ezt alakítja át date objektummá
weekday() visszaadja a hét adott napját egy egész számként, ahol hétfő indexe 0, a vasárnap indexe 6
isoweekday() visszaadja a hét adott napját egy egész számként, ahol hétfő indexe 1, a vasárnap indexe 7
Attribútum Leírás
year visszaadja az évet
month visszaadja a hónapot
day visszaadja a napot
import datetime


def fn_date():
    ma = datetime.date.today()  # Class method, ami visszaadja a mai napot date objektumként
    print(ma)
    print(type(ma))
    print("--")
    egy_nap = datetime.date(2021, 3, 10)
    print(egy_nap)
    egy_nap2 = datetime.date.fromisoformat("2021-03-08")
    print(egy_nap)
    egy_nap3 = datetime.datetime.strptime("2021 (év) 03 (hó) 10. (nap)", "%Y (év) %m (hó) %d. (nap)")
    print(egy_nap)
    print(egy_nap.strftime("Év: %Y, hónap: %m, nap: %d"))
    print(egy_nap.year)
    print(egy_nap.month)
    print(egy_nap.day)
    print("operátorok")
    print("<", egy_nap2 < egy_nap)
    print(">", egy_nap2 > egy_nap)
    print("==", egy_nap2 == egy_nap)
    if datetime.date(2020, 12, 31) < datetime.date.today() < datetime.date(2021, 4, 1):
        print("2021 első negyedévében vagyunk.")
    print("--")

Idő objektumok

A idő a datetime modul time osztályában találhatóak. Létrehozása: datetime.time(óra, perc, másodperc, mikroszekundum), amennyiben valamelyiket paramétert kihagyjuk, 0-lesz az alapértelmezett értéke. - 0 <= óra < 24 - 0 <= perc < 60 - 0 <= másodperc < 60 - 0 <= mikroszekundum < 1000000

Hozzá tartozó fontosabb metódusok és attribútumok:

Metódus Leírás
fromisoformat() paraméterként egy string-et vár (HH:MM:SS.ffffff vagy HH:MM:SS alakban), és ezt alakítja át time objektummá
Attribútum Leírás
hour visszaadja az órát
minute visszaadja a percet
second visszaadja a másodpercet
microsecond visszaadja a mikroszekundumot (a másodperc egymilliomod része)
min visszaadja a legkisebb időt ami a time(0, 0, 0, 0)
max visszaadja a legnagyobb időt ami a time(23, 59, 59, 999999)
import datetime


def fn_time():
    # time - csak az ido kezelesere (a datum nem szamit)
    # egy_idopillanat = datetime.time(12)
    # egy_idopillanat = datetime.time(12, 00)
    # egy_idopillanat = datetime.time(12, 0, 0)
    # egy_idopillanat = datetime.time(12, 00, 00, 123)
    egy_idopillanat = datetime.time(12, 10, 12, 123, datetime.timezone.utc)
    print("time", egy_idopillanat)
    print(egy_idopillanat.hour)
    # Vigyázat! A min az a lehető legkisebb értéke az objektumnak!
    print("min", egy_idopillanat.min)
    print("max", egy_idopillanat.max)
    print(egy_idopillanat.minute)
    print(egy_idopillanat.second)
    print(egy_idopillanat.microsecond)
    print("--")

Dátum és idő objektumok

A datetime modul datetime osztályában találhatóak. Létrehozása: datetime.datetime(year, month, day, hour, minute, second, microsecond, tzinfo), amennyiben valamelyiket paramétert kihagyjuk, 0-lesz az alapértelmezett értéke. Kötelező: year, month, day

Hozzá tartozó fontosabb metódusok és attribútumok:

Metódus Leírás
now() visszaadja a mostani dátumot és időt (megadható neki paraméternek időzóna tz) datetime objektumként
fromisoformat() paraméterként egy string-et vár (ISO formátumban) és ezt alakítja át datetime objektummá
strptime() paraméterként egy testszőlegesstring-et vár és ezt alakítja át datetime objektummá
weekday() visszaadja a hét adott napját egy egész számként, ahol Monday az 0 és a Sunday az 6
isoweekday() visszaadja a hét adott napját egy egész számként, ahol Monday az 1 és a Sunday az 7
datetime.combine() paramétere egy date és egy time ebből hoz létre egy datetime-ot
Attribútum Leírás
year visszaadja az évet
month visszaadja a hónapot (számként)
day visszaadja a napot (számként)
hour visszaadja az órát
minute visszaadja a percet
second visszaadja a másodpercet
microsecond visszaadja a mikroszekundumot (a másodperc egymilliomod része)
min visszaadja a legkisebb időt ami a time(0, 0, 0, 0)
max visszaadja a legnagyobb időt ami a time(23, 59, 59, 999999)
tzinfo időzóna`
strptime() format kód Leírás
%d nap számmal (01, 02, ..., 31)
%b hónap neve röviden (Jan, Feb, ..., Dec)
%B hónap neve hosszan (January, February, ..., December)
%m hónap számmal 01, 02, ..., 12
%y év számmal röviden (00, 01, ..., 99)
%Y év 4 jegyű számként (0001, 0002, ..., 9999)
%H óra 24-órás felbontásban (00, 01, ..., 23)
%I óra 12-órás felbontásban (01, 02, ..., 12)
%S másodperc számmal (00, 01, ..., 59)
%f mikroszekundum számmal (000000, 000001, ..., 999999)
import datetime


def fn_datetime():
    most = datetime.datetime.now()

    egy_nap = datetime.date(2021, 3, 10)
    egy_idopillanat = datetime.time(12, 10, 12, 123, datetime.timezone.utc)

    valamikor = datetime.datetime.combine(egy_nap, egy_idopillanat)
    print(most)
    print(valamikor)
    print(most.year)
    print(most.month)
    print(most.day)
    print(most.hour)
    print(most.minute)
    print(most.second)
    print(most.microsecond)
    print(most.tzinfo)
    # 0 - Monday 1 - Tuesday 2 - Wednesday 3 - Thursday 4 - Friday 5 - Saturday 6 - Sunday
    print(most.weekday())
    # 1 - Monday 2 - Tuesday 3 - Wednesday 4 - Thursday 5 - Friday 6 - Saturday 7 - Sunday
    print(most.isoweekday())
    print("--")

Különbség

A timedelta objektum 2 date vagy time közötti különbséget reprezentálja. Csak a napok, másodpercek, mikroszekundumok tárolódnak, a többit átalakítja. - 1 millisecond -> 1000 microseconds - 1 minute -> 60 seconds - 1 hour -> 3600 seconds - 1 week -> 7 days

Lehetséges értékek: - 0 <= mikroszekundumok < 1000000 - 0 <= másodpercek < 3600*24 - 999999999 <= napok <= 999999999

import datetime


def fn_timedelta():
    most = datetime.datetime.now()
    regebben = datetime.datetime(2021, 1, 1, 13, 33, 45, 10)

    delta = datetime.timedelta(days=10, hours=1, minutes=10, seconds=5, microseconds=100, milliseconds=98)
    print(most + delta)
    print(most - delta)
    print(delta.days)
    print(delta.seconds)
    print(delta.microseconds)
    delta = most - regebben
    print(delta)
    print(type(delta))
    print(type(delta))

Naptár

A calendar modulról részletesebben: https://docs.python.org/3/library/calendar.html

Fontosabb metódusai:

Metódus Leírás
month() Visszaad egy havi naptárat, paramétere: év, hónap
calendar() 3 oszlopos naptárat ad vissza, paramétere: év, hónap
isleap() Igazat ad, ha a paraméterben érkezett év szökőév, egyébként hamisat
leapdays() A 2 kapott paraméter (év) között visszaadja, hány darab szökőév volt
monthcalendar() Egy mátrix alapú naptárat ad vissza, 2 paramétere van: év, hónap
import calendar
import datetime

if __name__ == '__main__':
    most = datetime.datetime.now()

    naptar = calendar.month(most.year, most.month)
    print(naptar)

    print(calendar.calendar(most.year, 2, 2, 6, 3))

    # Hasznos funkciók
    print("Szökőév?", calendar.isleap(most.year))
    print("Szökőévek száma 2000 és 2020 között:", calendar.leapdays(2000, 2020))
    print(f"Mai nap: {calendar.day_name[most.weekday()]}")

    print("A jelenlegi hónap hetei")
    print(calendar.monthcalendar(most.year, most.month))

CSV kezelés

A csv modulról részletesen: https://docs.python.org/3/library/csv.html

Leírás
writer() csv fájl író létrehozása
reader() csv fájl olvasó létrehozása
DictReader() csv fájból dict-be olvas be
encoding karakterkódolás beállítása
delimiter elválasztójel beállítása
writerow() A kapott paramétert a writer fájl objektumába írja

Olvasás

import csv
import os

with open(os.path.join("kesesek.csv"), encoding="utf8") as fp:
    csv_reader = csv.reader(fp, delimiter=",")
    for row in csv_reader:
        print([r.strip() for r in row])

Ez a megoldás gyakorlatilag nem sokkal jobb, mintha mi magunk írtunk volna meg a beolvasást egy, felturbózva egy egyszerű split-tel.

import csv
import os

with open(os.path.join("hf2", "kesesek.csv"), encoding="utf8") as fp:
    csv_reader = csv.DictReader(fp, delimiter=",")
    for row in csv_reader:
        print(row)

Írás

import csv
import os


with open('kutyak.csv', mode='w') as kutya_adatok:
    kutya_writer = csv.writer(kutya_adatok, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)

    kutya_writer.writerow(['Bloki', 'labrador', 'fekete', 'soha'])
    kutya_writer.writerow(['Cukika', 'palotapincsi', 'feher', 'nyaron']

Hasonló a probléma, mint fentebb. Azonban itt is létezik jobb megoldás.

import csv
import os

with open('kutyak_jobb.csv', mode='w') as kutya_adatok:
    fieldnames = ['nev', 'fajta', 'szine', 'szor_hullas']

    kutya_writer = csv.DictWriter(kutya_adatok, fieldnames=fieldnames, lineterminator="\n")

    kutya_writer.writeheader()
    kutya_writer.writerow({'nev': 'Bloki', 'fajta': 'labrador', 'szine': 'fekete', 'szor_hullas': 'soha'})
    kutya_writer.writerow({'nev': 'Cukika', 'fajta': 'palotapincsi', 'szine': 'feher', 'szor_hullas': 'nyaron'})

kutyak = [
    {'nev': 'Bloki', 'fajta': 'labrador', 'szine': 'fekete', 'szor_hullas': 'soha'},
    {'nev': 'Cukika', 'fajta': 'palotapincsi', 'szine': 'feher', 'szor_hullas': 'nyaron'}
]

with open('kutyak_jobb2.csv', mode='w') as kutya_adatok:
    kutya_writer = csv.DictWriter(kutya_adatok, fieldnames=kutyak[0].keys(), lineterminator="\n")

    kutya_writer.writeheader()
    for k in kutyak:
        kutya_writer.writerow(k)

Egyszerű glob

import glob
import os

# for file_name in glob.glob('csv_fajlok/netflix_yearly_data/**/*.csv'):
for file_name in glob.glob('csv_fajlok/netflix_yearly_data/*.csv'):
    print(file_name)
    print(os.path.abspath(file_name))

    # szetvalasztas evtizedekre

Pathlib

import os
import pathlib

netflix_data_folder = os.path.join("csv_fajlok", "netflix_yearly_data")

p = pathlib.Path(netflix_data_folder)
print("p:", p)
print("abszolút útvonal:", p.absolute())
print("név:", p.name)
print("szülő:", p.parent)
print("nagyszülő:", p.parent.parent)
print("létezik:", p.exists())
print("cwd:", p.cwd())
print("posix:", p.as_posix())
print("uri:", p.absolute().as_uri())

for fajl in p.glob("**/*.csv"):
    print(fajl)
    # összeolvasztás

p = p.parent

foka = p.joinpath("teszt_foka.txt")
print("létezik:", foka.exists())
with foka.open("w") as fp:
    fp.write("Seals can sleep underwater and usually only come on land to escape predators like whales and sharks, as well as to mate, give birth, feed and moult.")
print("létezik:", foka.exists())
# A teljes útvonal megadása szükséges
# foka.rename("foka_teny.txt")

Reguláris kifejezések

import os
import re

# Amire szükség lesz: basic regex ismeretek
# Help: https://regex101.com/

text = """Akkor nem kell!
Akkor nem kell!!!!!
Akkor nem kell!!
Akkor nem kell!!444!4!4!!!!
Akkor nem kell!!444!4!4!4!4!
"""

# Alap keresés regex segítségével
# Flagek:
# re.I == re.IGNORECASE
# re.M == re.MULTILINE
# re.S == re.DOTALL
# re.X == re.VERBOSE
# re.U == re.UNICODE
# re.L == re.LOCALE
# re.DEBUG
match = re.search(r".+!{2,}$", text, flags=re.MULTILINE | re.IGNORECASE)
print(match)
if match:
    print("Van találat!")
    print(match.groups())
match = re.search(r".+!{100,}$", text, flags=re.MULTILINE | re.IGNORECASE)
if match:
    print("Van találat!")

# Kiegészíteni a regexet

# EMAIL_REGEX = re.compile("^\\S+@\\S+\\.\\S+$")
# EMAIL_REGEX = re.compile(r"^\S+@\S+\.\S+$")
EMAIL_REGEX = re.compile(r"\S+@\S+\.\S+$")
CIMEK = ["Alma@kukac.hamm", "jajj@gmail.com", "cica@vagyok.hu", "kutya.vagyok.hu", "nem tudom mi ez @gmail.com",
         "nem értem", "denever@eset.hu", "Asszem valami cipofuzo23@gmail.com"]

print("---")
for email in CIMEK:
    print(email, "valid:", "igen" if EMAIL_REGEX.search(email) else "nem")
print("---")
for email in CIMEK:
    print(email, "valid:", "igen" if EMAIL_REGEX.match(email) else "nem")
print("---")

with open(os.path.join("szoveg", "cirmatlan_cica.txt"), encoding="utf8") as fp:
    cica_mese = fp.read()

# Csak egy találatot ad vissza
print(re.search("tényle{2,}g", cica_mese, flags=re.U | re.I))

for talalat in re.findall("ténylee+g", cica_mese, re.U | re.I):
    print(talalat)

for talalat in re.finditer("ténylee+g", cica_mese, re.U | re.I):
    print("találat", talalat)

print("---")

# re.sub házi feladat

EMAIL_REGEX = re.compile(r"^(\S+)@(\S+)\.(\S+)$")
for email in CIMEK:
    match = EMAIL_REGEX.match(email)
    if match:
        print(match.groups())
        print(match.group(0))
        print(match.group(1))
        print(match.group(2))
        print(match.group(3))

Ó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.

Nőnap

Készíts egy statisztikát arról, hogy az utóbbi 30 évben milyen napokra esett a Nemzetközi nőnap (március 8). A függvény térjen vissza egy dictionary objektummal.

def nonap_statisztika():
    pass

Ennek visszatérési értéke (példa):

{'hetfo': 4, 'kedd': 2, 'szerda': 5, 'csutortok': 5, 'pentek': 5, 'szombat': 4, 'vasarnap': 5}

Péntek 13

Számoljuk ki, hogy az elmúlt 5 évben hányszor volt pénteken a hónap 13. napja. A függvény írja ki a péntek 13-i dátumokat, majd térjen vissza a darabszámmal. Egészítsd ki, hogy a felhasználótól kérje be, hogy az utóbbi hány évre kíváncsi.

def pentek13():
    pass

Szétbontás évtizedekre

A csv_fajlok mappában lévő netflix_yearly_data mappa mellé készítsünk még egy mappát (Python kódból), netflix_decade_data néven, amibe legyenek berendezve a csv fájlok évtizedek szerint, például: 1910_1920, 1920_1930, stb.

Tipp

Használd a glob modult, az shutil modullal együtt! Vagy pedig a pathlib modul Path osztályát!

Idegroncs detektor advanced edition

Egészítsd ki az órai példát, hogy ne csak a "!!+" regex szerint találja meg a felkiáltójel helytelen használóit, hanem a felkiáltójelek között tetszőlegesen, tetszőleges darabszámban elhelyezett "4" karakterekkel is felismerje azt, amikor valaki idegességében írt egy mondatot.

Adatösszevonás

Vond össze az összes fájlt egyetlen nagy csv fájlba a csv_fajlok mappában lévő netflix_yearly_data mappából.

Házi feladat

Csere

Önállóan feldolgozni a re.sub függvényt az alábbi oldalról: https://docs.python.org/3/library/re.html#re.sub

Kapcsolódó linkek

Python regex "cheat sheet"


Utolsó frissítés: 2023-02-21 14:46:51