Lekce 14 - Magické metody Pythonu - Matematické
V minulé lekci, Magické metody v Pythonu, jsme se věnovali magickým metodám.
V tomto Python tutoriálu budeme probírat magické metody zaměřené spíše na 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)
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.
V další lekci, Magické metody v Pythonu - Kolekce a deskriptory, se podíváme na magické metody kolekcí, metody pro řízení atributů a na deskriptory v Pythonu.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 157x (1.87 kB)
Aplikace je včetně zdrojových kódů v jazyce Python