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 [10]:
class CeleCislo(int):
    def je_sude(self):
        return self % 2 == 0
    
    def __repr__(self):
        return "<Cele cislo {}>".format(self)
In [11]:
y = 5
y
Out[11]:
5
In [12]:
x = CeleCislo(5)
x
Out[12]:
<Cele cislo 5>

Kompatibilita

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

In [13]:
a = 5
b = CeleCislo(7)
In [14]:
a + b
Out[14]:
12
In [15]:
a - b
Out[15]:
-2
In [16]:
a < b
Out[16]:
True
In [17]:
b >= a
Out[17]:
True

Vlastní objekty a speciální metody

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

In [19]:
class Osoba:
    def __init__(self, jmeno, rc):
        self.jmeno = jmeno
        self.rc = rc
    
    def __repr__(self):
        return "<Osoba jmena '{}' a RC '{}'".format(self.jmeno, self.rc)
In [32]:
o = Osoba("Pepa", 880101)
o
Out[32]:
<Osoba jmena 'Pepa' a RC '880101'

Matematika

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

In [21]:
class Osoba:
    def __init__(self, jmeno, rc):
        self.jmeno = jmeno
        self.rc = rc
    
    def __repr__(self):
        return "<Osoba jmena '{}' a RC '{}'".format(self.jmeno, self.rc)
    
    def __add__(self, other):
        return self.rc + other.rc
In [33]:
o1 = Osoba("Pepa", 880101)
o2 = Osoba("Karel", 660101)

o1 + o2
Out[33]:
1540202
In [23]:
o1 - o2
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-23-228b50e50c4a> in <module>()
----> 1 o1 - o2

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

Porovnávání

In [24]:
class Osoba:
    def __init__(self, jmeno, rc):
        self.jmeno = jmeno
        self.rc = rc
    
    def __repr__(self):
        return "<Osoba jmena '{}' a RC '{}'".format(self.jmeno, self.rc)
    
    def __add__(self, other):
        return self.rc + other.rc

    def __lt__(self, other):
        return self.jmeno < other.jmeno
In [34]:
o1 = Osoba("Pepa", 880101)
o2 = Osoba("Zikmund", 660101)
o3 = Osoba("Alois", 780101)

o1 < o2
Out[34]:
True
In [35]:
o2 < o3
Out[35]:
False

Řazení

In [36]:
seznam = [o1, o2, o3]
seznam
Out[36]:
[<Osoba jmena 'Pepa' a RC '880101',
 <Osoba jmena 'Zikmund' a RC '660101',
 <Osoba jmena 'Alois' a RC '780101']
In [37]:
sorted(seznam)
Out[37]:
[<Osoba jmena 'Alois' a RC '780101',
 <Osoba jmena 'Pepa' a RC '880101',
 <Osoba jmena 'Zikmund' a RC '660101']