Tegyük fel, hogy olyan sorozatokkal, illetve sorozattípusú konténerobjektumokkal dolgozunk, amelyekben vegyesen fordulnak elő True és False igazságértékű elemek. A programunk egy adott pontján azonban már csak olyan sorozatot szabad feldolgozni, amelyben csak True igazságértékű elemek szerepelnek. A feladat tehát az, hogy írjunk olyan függvényt, amely az argumentumként kapott listából kiszűri, eltávolítja a False igazságértékű elemeket és egy olyan listával tér vissza, amelyben már minden elem True igazságértékű.
Erre több megoldás is szóba jöhet.
Az egyik lehetőség a listaépítő kifejezés (list comprehension) alkalmazása. Ez látható az alábbi drop_falsy_items1() függvényben. Itt a visszatérési értéket jelentő listaépítő kifejezésben a feltétel megadásakor nem szükséges a „bool(element) == True” kifejezést kiírni, hanem kihasználva, hogy az „if” utáni kifejezésnek automatikusan az igazságértéke lesz figyelembe véve, egyszerűen elég csak az, hogy „if element”.
|
1 2 3 4 5 6 7 |
def drop_falsy_items1(seq: list): """Az argumentumként megadott listából kiszűri a False igazságértékű elemeket és egy olyan listával tér vissza, amelyben minden elem True igazságértékű. """ return [element for element in seq if element] |
Egy másik megoldás, hogy a filter() beépített függvényt használjuk. Itt is van tömör leírási lehetőség. Ugyanis ahelyett, hogy a filter() első argumentumaként egy olyan függvényt adnánk meg, amely az aktuális sorozatelem igazságértékével tér vissza, ugyanezt érjük, ha itt a None értéket adjuk meg. Ezt mutatja a drop_falsy_items2() függvény.
|
1 2 3 4 5 6 7 |
def drop_falsy_items2(seq: list): """Az argumentumként megadott listából kiszűri a False igazságértékű elemeket és egy olyan listával tér vissza, amelyben minden elem True igazságértékű. """ return list(filter(None, seq)) |
A teszteléshez vegyük sorra, hogy mely objektumoknak biztosan False az igazságértéke. Ezek:
– a 0, 0.0, 0e0 és 0+0j számok
– az üres beépített konténerobjektumok (pl. [], (), {}, set())
– az olyan objektumok, amelyeknél a __bool__ metódus False értékkel tér vissza.
– az olyan objektumok, amelyeknél a __len__ metódus visszatérési értéke 0.
Ez utóbbi kettő teszteléséhez készítettünk két egyszerű egyéni osztályt, amelyek definíciója ez:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class AlwaysFalse1: """Ennek az osztálynak a példányai mindig False igazságértékűek.""" def __bool__(self) -> bool: return False class AlwaysFalse2: """Ennek az osztálynak a példányai mindig False igazságértékűek.""" def __len__(self) -> int: return 0 |
A tesztelést egy olyan listával végezzük, amelyben kettő kivételével minden elem False igazságértékű.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
from timeit import timeit # TESZT sequence = [1, None, False, 0, '', (), [], {}, set(), bytes(), bytearray(), range(0), AlwaysFalse1(), AlwaysFalse2(), 2] print(drop_falsy_items1(sequence)) print(drop_falsy_items2(sequence)) # Eredmény: [1, 2] mindkét esetben. for test_stmt in ('drop_falsy_items1(sequence)', 'drop_falsy_items2(sequence)'): t = timeit(stmt=test_stmt, number=10000000, globals=globals()) print(f'{t:.3f}') # Eredmény: # 4.836 # 3.728 |
A vártnak megfelelően mindkét függvény az elvárások szerint működik.
A két megoldás közötti választás több szempont alapján történhet. A filter() függvény használata kevésbé olvasható, mint a listaépítő kifejezés, mert ha valaki nem ismeri a None argumentum e hatását, akkor utána kell néznie. Ugyanakkor, ha a futási idő lényeges szempont, akkor ezt érdemes választani, mert ahogy az erre vonatkozó teszteredményekből látszik a filter(), ha kicsivel is, de jobban teljesít.
Az objektumok igazságértékét a Python tudásépítés lépésről lépésre című e-könyvben a „Mindenkinek megvan a maga igazsága” fejezet tárgyalja. A __bool__ és __len__ metódusokról a „Speciális metódus és adatattribútumok”, valamint a „Mágikus metódusok egyedi igényre szabott osztályokban” című fejezetekben lehet olvasni példákkal együtt. A futási idő méréséről és a timit modulról a „A programvégrehajtás felfüggesztése és a futási idő mérése” című alfejezet nyújt ismereteket a „Készétel fogyasztás – a szabványos könyvtár moduljainak használata” fejezeten belül.