A Pythonban minden objektum rendelkezik logikai igaz vagy hamis értékkel. Ez azt jelenti, hogy bármely objektumra elvégezhető a logikai értékvizsgálat.
Egy objektum logikai értékét közvetlenül úgy kérdezhetjük le, hogy a vizsgált objektumot a bool() konstruktor zárójelei közé írjuk, és ennek eredményeképpen True vagy False értéket kapunk.
Alapértelmezésben minden objektum logikai igaz (True) értékkel rendelkezik. Ez alól kivételt képeznek:
- Az üres konténerek. Pl.: ”, (), [], {}, set(), frozenset(), bytes(), bytearray(), range(0).
- Bármelyik számtípus nulla értéke. Pl.: 0, 0.0, 0j, 0e0.
- A None és False konstansok, vagy ezeket eredményező kifejezések.
- Azok a saját készítésű objektumok, amelyeket a definíciójukban szándékosan False értékre állítunk a __bool__ metódus implementálásával.
Azért hasznos, hogy az objektumoknak van igazságértéke, mert:
- rövidebb és olvashatóbb feltételvizsgálatokat tesz lehetővé,
- feltételvizsgálatoknál egységesen lehet kezelni a különböző adattípusokat,
- megkönnyíti a logikai műveletek használatát,
- hozzájárul a Pythonra jellemző tömör és jól olvasható kódhoz.
Ennek eredményeként kevesebb kódot kell írni, miközben a program szándéka világosabb marad.
Mindennek demonstrálására vegyünk egy példát, amely modellezi egy webáruház megrendelési adatainak összegzését. Ezt mutatja az alábbi programkód.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
class Cart: """Bevásárlókosár-osztály. A kosár a benne lévő termékeket egy listában tárolja.""" def __init__(self, items: list): self.items = items def __str__(self): return str(self.items) def __len__(self): return len(self.items) # A vásárlók adatai. customers = [{"name": "Ádám", "nickname": "", "email": "adam@example.com", "discount": 1500, "cart": Cart(["alma", "körte"])}, {"name": "", "nickname": "", "email": "", "discount": 0, "cart": Cart([])}, {"name": "Éva", "nickname": "", "email": "eva@dummymail.com", "discount": 2000, "cart": Cart([])}, {"name": "Sándor", "nickname": "Sanyi", "email": "", "discount": 0, "cart": Cart(["kenyér"])} ] for customer in customers: # Csak azon vásárlók megrendelése kerül feldolgozásra, akiknek nem üres a kosara. if len(customer["cart"]) > 0: # Az összegzésben a becenév lesz megjelenítve, ha adott, egyébként a normál név. if customer["nickname"] != "": display_name = customer["nickname"] else: display_name = customer["name"] print(f"Vásárló: {display_name}") # Információkat írunk ki a kosár tartalmáról. print(f"Kosárban: {len(customer['cart'])} termék: {str(customer["cart"]).strip('[]')}") # Csak akkor írjuk ki a kedvezményt, ha annak összege nem nulla. if (discount := customer["discount"]) > 0: print(f"Igénybe vehető kedvezmény: {discount} Ft") # Ha adott az e-mail cím, akkor ezt is megjelenítjük a megrendelés jóváhagyásához. if customer["email"] != "": print(f"Értesítési email cím: {customer['email']}") print() # Eredmény: # Vásárló: Ádám # Kosárban: 2 termék: 'alma', 'körte' # Igénybe vehető kedvezmény: 1500 Ft # Értesítési email cím: adam@example.com # # Vásárló: Sanyi # Kosárban: 1 termék: 'kenyér' |
A program sorban egymás után veszi a vásárlókat, és a következő adatokat jeleníti meg, ha azok rendelkezésre állnak:
- a vásárló neve (preferáltan a becenév, ha adott),
- a kosár tartalmára vonatkozó információk,
- az eddigi vásárlások alapján igénybe vehető kedvezmény,
- az értesítéshez használható e-mail cím.
Itt nem használtuk ki az objektumok igazságértékét, ezért mint látható, a feltételvizsgálatoknál logikai operátorok, zárójelezés, függvényhívás és szelekciós utasítás is szerepel.
Ha azonban kihasználjuk azt, hogy az objektumoknak van igazságértéke, akkor az előző programkódot a ciklustörzsben az alábbiak szerint módosíthatjuk.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
class Cart: """Bevásárlókosár-osztály. A kosár a benne lévő termékeket egy listában tárolja.""" def __init__(self, items: list): self.items = items def __str__(self): return str(self.items) def __len__(self): return len(self.items) # A vásárlók adatai. customers = [{"name": "Ádám", "nickname": "", "email": "adam@example.com", "discount": 1500, "cart": Cart(["alma", "körte"])}, {"name": "", "nickname": "", "email": "", "discount": 0, "cart": Cart([])}, {"name": "Éva", "nickname": "", "email": "eva@dummymail.com", "discount": 2000, "cart": Cart([])}, {"name": "Sándor", "nickname": "Sanyi", "email": "", "discount": 0, "cart": Cart(["kenyér"])} ] for customer in customers: # Csak azon vásárlók megrendelése kerül feldolgozásra, akiknek nem üres a kosara. if customer["cart"]: # Az összegzésben a becenév lesz megjelenítve, ha adott, egyébként a normál név. display_name = customer["nickname"] or customer["name"] print(f"Vásárló: {display_name}") # Információkat írunk ki a kosár tartalmáról. print(f"Kosárban: {len(customer['cart'])} termék: {str(customer["cart"]).strip('[]')}") # Csak akkor írjuk ki a kedvezményt, ha annak összege nem nulla. if discount := customer["discount"]: print(f"Igénybe vehető kedvezmény: {discount} Ft") # Ha adott az e-mail cím, akkor ezt is megjelenítjük a megrendelés jóváhagyásához. if customer["email"]: print(f"Értesítési email cím: {customer['email']}") print() # Eredmény: # Vásárló: Ádám # Kosárban: 2 termék: 'alma', 'körte' # Igénybe vehető kedvezmény: 1500 Ft # Értesítési email cím: adam@example.com # # Vásárló: Sanyi # Kosárban: 1 termék: 'kenyér' |
E változatban a feltételvizsgálatoknál nincs szükség logikai operátorokra, zárójelezésre, függvényhívásra, és a szelekciós utasítás is helyettesíthető egy logikai kifejezéssel. Ezzel a kód inkább az üzleti logikát fejezi ki, és kevésbé az ellenőrzések technikai részleteit. Az objektumok igazságértéke tehát nem csupán gépelést spórol, hanem magasabb absztrakciós szinten teszi olvashatóvá a programot.
Felmerülhet a kérdés, hogy miért működik az if customer["cart"] ilyen egyszerűen, vagyis anélkül, hogy a Cart osztályban definiáltuk volna a __bool__ metódust? A válasz a Python igazságérték-meghatározási sorrendjében rejlik.
Amikor a Python egy objektum logikai értékét meghatározza, akkor a következőket teszi: ha van __bool__ metódus, akkor azt meghívja és annak eredményét használja. Ha nincs __bool__, de van __len__, akkor azt hívja meg. Ha ennek eredménye 0, akkor az objektum False értékű, egyébként True. Ha az objektumban sem a __bool__, sem a __len__ nincs implementálva, akkor az objektum alapértelmezetten True értékű.
Mivel a Cart implementálja a __len__ metódust, ezért az igazságérték meghatározásánál ennek visszatérési értéke lesz figyelembe véve.
A __bool__ metódus felülírásával kapcsolatos tudnivalókról a Python tudásépítés lépésről lépésre az alapoktól az első asztali alkalmazásig című e-könyv „Konténerek megvalósítása” fejezetében tájékozódhatunk.