November Black Friday C# týden
Black Friday je tu! Využij jedinečnou příležitost a získej až 80 % znalostí navíc zdarma! Více zde
Pouze tento týden sleva až 80 % na e-learning týkající se C#

Lekce 12 - Magické metody Pythonu - Matematické

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Magické metody v Pythonu, jsme se věnovali magickým metodám. V tomto Python tutoriálu budeme pokračovat s magickými metodami. Tentokrát si ukážeme speciální metody pro matematické operátory. Na třídě Vector si také ukážeme jejich použití.

Obyčejné operátory

Tyto operátory se volají standardně na objektu a, pokud je použijeme takto:

c = a + b

Objekt a je předán jako parametr self a objekt b jako parametr other.

__add__(self, other)

Metoda se zavolá na prvním objektu při použití operátoru +:

c = a + b

__sub__(self, other)

Metoda se zavolá při použití operátoru odečítání -:

c = a - b

__mul__(self, other)

Metoda se zavolá při použití operátoru násobení *:

c = a * b

__truediv__(self, other)

Metoda se zavolá při použití operátoru dělení /:

c = a / b

__floordiv__(self, other)

Metoda se zavolá při použití operátoru celočíselné dělení //:

c = a // b

__mod__(self, other)

Metoda se zavolá při použití operátoru zbytek po dělení - modulo %:

c = a % b

__divmod__(self, other)

Vrací dvojici (a // b, a % b) pro celá čísla:

c = divmod(a, b)

__pow__(self, other, modulo)

Metoda se spustí když použijeme operátor mocniny **. Metoda by měla být schopná brát i třetí, nepovinný argument (modulo) - https://docs.python.org/…nctions.html#pow :

c = a ** b

__lshift__(self, other)

Spuštěno při použití operátoru pro bitový posun vlevo:

c = a << b

__rshift__(self, other)

Spuštěno při použití operátoru pro bitový posun vpravo:

c = a >> b

__and__(self, other)

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Spuštěno při použití bitového operátoru AND &:

c = a & b

__xor__(self, other)

Spuštěno při použití bitového operátoru XOR ^ (non-ekvivalence):

c = a ^ b

__or__(self, other)

Spuštěno při použití bitového operátoru OR |:

c = a | b

Prohozené operátory

Prohozené (reversed) operátory se zavolají na druhém objektu, pokud není poskytnuta jejich implementace na prvním objektu.

Např.:

sth = 1 + my_object

Pokud int nepodporuje magickou metodu __add__(), což pravděpodobně ne, je zavolána metoda __radd__() na my_object.

Tyto operátory se volají standardně na objektu b, přičemž objekt b je parametr self a objekt a je parametr other

  • __radd__(self, other) - Sčítání
  • __rsub__(self, other) - Odečítání
  • __rmul__(self, other) - Násobení
  • __rtruediv__(self, other) - Pravé dělení
  • __rfloordiv__(self, other) - Celočíselné dělení
  • __rmod__(self, other) - Zbytek po dělení - modulo
  • __rdivmod__(self, other) - Vrací dvojici (a // b, a % b) pro celá čísla.
  • __rpow__(self, other, modulo) - Mocnina. Metoda by měla být schopná brát i třetí, nepovinný argument (modulo).

Funkce pow(): https://docs.python.org/…nctions.html#pow

  • __rlshift__(self, other) - Bitový posun vlevo
  • __rrshift__(self, other) - Bitový posun vpravo
  • __rand__(self, other) - Logická funkce AND
  • __rxor__(self, other) - Logická funkce XOR (non-ekvivalence)
  • __ror__(self, other) - Logická funkce OR

Operátory in place

Tyto operátory umožňují zkrácenou notaci (na místě). Parametry metod jsou self a other, ale vrací modifikovaný self. Pokud některá metoda neexistuje, Python se ji pokusí emulovat s využitím definovaných metod.

Příklad:

my_object += 1

Python zavolá metodu __iadd__(). V případě neúspěchu zavolá metodu __add__() tímto způsobem:

temp = my_object + 1 # zavolá __add__()
my_object = temp
  • __iadd__(self, other) - Sčítání
  • __isub__(self, other) - Odečítání
  • __imul__(self, other) - Násobení
  • __itruediv__(self, other) - Pravé dělení
  • __ifloordiv__(self, other) - Celočíselné dělení
  • __imod__(self, other) - Zbytek po dělení - modulo
  • __ipow__(self, other, modulo) - Mocnina. Metoda by měla být schopná brát i třetí, nepovinný argument (modulo).
  • __ilshift__(self, other) - Bitový posun vlevo
  • __irshift__(self, other) - Bitový posun vpravo
  • __iand__(self, other) - Logická funkce AND
  • __ixor__(self, other) - Logická funkce XOR (non-ekvivalence)
  • __ior__(self, other) - Logická funkce OR

Další magické metody

__neg__(self)

Unární mínus

-a

__pos__(self)

Unární plus

+a

__abs__(self)

Absolutní hodnota, implementuje chování pro funkci abs()

abs(a)

__invert__(self)

Unární inverze

~a

__complex__(self)

Implementace chování pro funkci complex()

complex(a)

__int__(self)

Implementace chování pro funkci int()

int(a)

__float__(self)

Implementace chování pro funkci float()

float(a)

__round__(self, n)

Implementace chování pro funkci round()

round(a)

__index__(self)

Python tuto metodu používá při konverzi numerických typů na int, například při ořezávání nebo pro použití vestavěných funkcí bin(), hex() a oct(). Tato metoda by měla vracet stejný výsledek jako magická metoda __int__(). A navíc by měla vracet celé číslo (int).

Ukázka některých metod

Vytvořme si jednoduchou třídu Vector, uchovávající složky x a y. Na třídě si zkusíme implementovat některé ze zmíněných magických metod:

class Vector:

    def __init__(self, x, y):
        self.x = float(x)
        self.y = float(y)

    def __str__(self):
        return "({0.x}, {0.y})".format(self)

    ...

Začátek je pravděpodobně jasný. V metodě __str__() získáváme ze self atributy x a y.

def __add__(self, other):
    if isinstance(other, Vector):
        return Vector(self.x+other.x, self.y+other.y)
    elif issubclass(type(other), Sequence):
        if len(other) == 2:
            return Vector(self.x+other[0], self.y+other[1])
    raise NotImplemented

Prvně porovnáme, zda je druhý objekt také vektor. Pokud ano, vrátíme součet x-ových a y-ových složek jako nový vektor.

Další větvení je již složitější. Za pomoci vestavěné funkce issubclass() kontrolujeme, jestli je třída druhého objektu podtřídou Sequence z modulu collections.abc. Díky tomu můžeme na objektu použít funkci len() a získat z objektu první a druhý prvek. A to bez obav, že by to daný objekt nepodporoval. Pokud obě větve selžou a nic nevrátí, vyvolá se výjimka NotImplemented.

def __mul__(self, other):
    if issubclass(type(other), Real):
        return Vector(self.x * other, self.y * other)
    raise NotImplemented

Zde kontrolujeme, jestli je other podtřídou třídy Real (reálné číslo) z modulu numbers. Proto můžeme vektor vynásobit intem nebo floatem a vyhnout se zbytečnému větvení a kontrolování typů objektu.

Uvedené třídy z modulů numbers a collections.abc jsou ve skutečnosti abstraktní bázové třídy, tedy třídy, u kterých se "zavazujeme" dodržet určité rozhraní objektů, pokud je zdědíme. O tom ale zase až v příští lekci, Magické metody v Pythonu - Kolekce a deskriptory.


 

Stáhnout

Staženo 48x (1.87 kB)
Aplikace je včetně zdrojových kódů v jazyce python

 

 

Aktivity (3)

 

 

Komentáře

Avatar
jan.ruzicka01:13.8.2015 20:20
  1. Máš tam dvakrát "__neg__", přičemž ve druhém případě tam má být "__pos__".
  2. Máš tam dvakrát v kódu "~a", přičemž ve druhém případě tam má být "int(a)".

Jinak super článek (možná bys měl zmínit i "__div__", přeci jen je to staré dobré 'klasické' dělení).

Odpovědět
13.8.2015 20:20
Važme si diverzity jazyků.
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
gcx11
Redaktor
Avatar
Odpovídá na jan.ruzicka01
gcx11:13.8.2015 21:28

Ahoj, díky za opravu :)

__div__() je pouze v Pythonu 2, co jsem koukal, v Python 3 se místo něj používá __truediv__()

 
Odpovědět
13.8.2015 21:28
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.