Domácí projekt - vlastní třída pro celá čísla

Vytvoř si vlastní třídu pro celá čísla tak, aby tato nová třída měla všechny vlastnosti a schopnosti běžných celých čísel v Pythonu (objekty bude možné sčítat, odečítat, porovnávat atp.) a navíc měla metodu pro rozpoznání, zda je číslo v objektu sudé nebo liché jménem je_sude(), která bude vracet True nebo False.

Řešení vlastní metody

Nejsmazší je dědit přímo z třídy int a přidat jen jednu vlastní metodu.


In [1]:
class CeleCislo(int):
    def je_sude(self):
        return self % 2 == 0

In [2]:
x = CeleCislo(5)
x.je_sude()


Out[2]:
False

In [3]:
y = CeleCislo(6)
y.je_sude()


Out[3]:
True

Řešení bonusu - vlastní metody repr

Metoda __repr__ vrací řetězec, který reprezentuje objekt například při výpisu v interaktivní konzoli. Tato metoda může vracet libovolný řetězec.


In [4]:
class CeleCislo(int):
    def je_sude(self):
        return self % 2 == 0
    
    def __repr__(self):
        return "<Cele cislo {}>".format(self)

In [5]:
y = 5
y


Out[5]:
5

In [6]:
x = CeleCislo(5)
x


Out[6]:
<Cele cislo 5>

Kompatibilita

Kompatibilita zůstala díky dědění zachována.


In [7]:
a = 5
b = CeleCislo(7)

In [8]:
a + b


Out[8]:
12

In [9]:
a - b


Out[9]:
-2

In [10]:
a < b


Out[10]:
True

In [11]:
b >= a


Out[11]:
True

Vlastní objekty a speciální metody

Pro domácí projekt to nebylo potřeba, ale pojďme si zkusit vytvořit vlastní třídu s implementovanými metodami pro využití operátorů v Pythonu.


In [12]:
class Pizza:
    def __init__(self, jmeno, ingredience):
        self.jmeno = jmeno
        self.ingredience = ingredience
    
    def __repr__(self):
        return "<Pizza '{}' na které je '{}'".format(self.jmeno, self.ingredience)

In [13]:
p = Pizza("salámová", ["sýr", "paprikáš", "suchý salám"])
p


Out[13]:
<Pizza 'salámová' na které je '['sýr', 'paprikáš', 'suchý salám']'

Matematika

Pro matematické operátory existují speciální metody, jejichž názvy odpovídají použitým operátorům/operacím.


In [14]:
class Pizza:
    def __init__(self, jmeno, ingredience):
        self.jmeno = jmeno
        self.ingredience = ingredience
    
    def __repr__(self):
        return "<Pizza '{}' na které je '{}'".format(self.jmeno, self.ingredience)
    
    def __add__(self, other):
        jmeno = self.jmeno + " " + other.jmeno
        ingredience = self.ingredience + other.ingredience
        return Pizza(jmeno, ingredience)

In [15]:
p1 = Pizza("salámová", ["sýr", "paprikáš", "suchý salám"])
p2 = Pizza("hawai", ["máslo", "ananas"])

In [16]:
p1 + p2


Out[16]:
<Pizza 'salámová hawai' na které je '['sýr', 'paprikáš', 'suchý salám', 'máslo', 'ananas']'

In [17]:
p2 - p1


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-17-f084741e9568> in <module>
----> 1 p2 - p1

TypeError: unsupported operand type(s) for -: 'Pizza' and 'Pizza'

Porovnávání

Pro porovnání máme také speciální metody - pro každý operátor jednu.


In [18]:
class Pizza:
    def __init__(self, jmeno, ingredience):
        self.jmeno = jmeno
        self.ingredience = ingredience
    
    def __repr__(self):
        return "<Pizza '{}' na které je '{}'".format(self.jmeno, self.ingredience)
    
    def __add__(self, other):
        jmeno = self.jmeno + " " + other.jmeno
        ingredience = self.ingredience + other.ingredience
        return Pizza(jmeno, ingredience)
    
    def __lt__(self, other):
        return len(self.ingredience) < len(other.ingredience)

In [19]:
p1 = Pizza("salámová", ["sýr", "paprikáš", "suchý salám"])
p2 = Pizza("hawai", ["máslo", "ananas"])
p3 = Pizza("pro chude", ["eidam"])
p4 = p1 + p2

In [20]:
p3 < p1


Out[20]:
True

In [21]:
p3 > p1


Out[21]:
False

In [22]:
p4 < p2


Out[22]:
False

Řazení

Řazení je jen speciální případ porovnávání, kdy se mezi sebou porovnají všechny prvky a podle výsledku jednotlivých porovnání se seřadí. K tomu nám stačí mít implementovánu alespoň metodu __lt__.


In [23]:
pizzy = [p1, p2, p3, p4]
pizzy


Out[23]:
[<Pizza 'salámová' na které je '['sýr', 'paprikáš', 'suchý salám']',
 <Pizza 'hawai' na které je '['máslo', 'ananas']',
 <Pizza 'pro chude' na které je '['eidam']',
 <Pizza 'salámová hawai' na které je '['sýr', 'paprikáš', 'suchý salám', 'máslo', 'ananas']']

In [24]:
sorted(pizzy)


Out[24]:
[<Pizza 'pro chude' na které je '['eidam']',
 <Pizza 'hawai' na které je '['máslo', 'ananas']',
 <Pizza 'salámová' na které je '['sýr', 'paprikáš', 'suchý salám']',
 <Pizza 'salámová hawai' na které je '['sýr', 'paprikáš', 'suchý salám', 'máslo', 'ananas']']

Seznam všech speciálních metod a jejich chování najdeš klasicky v dokumentaci Pythonu.