Einführung
In diesem Tutorial werden wir uns mit Python-Magie-Methoden befassen, die mit numerischen Operationen zusammenhängen. Magie-Methoden sind spezielle Methoden in Python-Klassen, die mit doppelten Unterstrichen (__) beginnen und enden. Sie werden auch als "dunder"-Methoden (doppelte Unterstriche) bezeichnet.
Diese Magie-Methoden ermöglichen es Ihnen, zu definieren, wie Instanzen Ihrer Klasse bei bestimmten Operationen wie Addition oder Subtraktion verhalten.
Wir werden die folgenden Abschnitte behandeln:
- Eindeutige Operatoren
- Binäre Operatoren
- In-place-Operationen
Lassen Sie uns beginnen!
Eindeutige Operatoren
Eindeutige Operationen sind Operationen, die einen einzelnen Operanden beinhalten, wie Negation, Betrag usw.
Lassen Sie uns mit einem einfachen Objekt beginnen. In number.py erstellen Sie eine Klasse namens MyNumber, die ein Attribut value hat.
class MyNumber:
def __init__(self, value: float):
self.value = value
__neg__
Die __neg__-Magie-Methode definiert, wie die Negationsoperation verhalten soll. Wenn Sie den --Operator auf einer Instanz Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __neg__(self) -> 'MyNumber':
"""Gibt die Negation des Wertes der Instanz zurück."""
return MyNumber(-self.value)
__abs__
Die __abs__-Magie-Methode definiert, wie die Betragsoperation verhalten soll. Wenn Sie die abs()-Funktion auf einer Instanz Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __abs__(self) -> 'MyNumber':
"""Gibt den Betrag des Wertes der Instanz zurück."""
return MyNumber(abs(self.value))
__round__
Die __round__-Magie-Methode definiert, wie die Rundungsoperation verhalten soll. Wenn Sie die round()-Funktion auf einer Instanz Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __round__(self, ndigits: int = None) -> 'MyNumber':
"""Rundet den Wert der Instanz auf die nächste ganze Zahl oder die angegebene Anzahl von Stellen."""
return MyNumber(round(self.value, ndigits))
__floor__
Die __floor__-Magie-Methode definiert, wie die Bodenfunktion verhalten soll. Wenn Sie die math.floor()-Funktion auf einer Instanz Ihrer Klasse verwenden, wird diese Methode aufgerufen.
## math-Modul sollte am Anfang von number.py importiert werden
import math
#... (vorheriger Code in number.py)
def __floor__(self) -> 'MyNumber':
"""Gibt die größte ganze Zahl zurück, die kleiner oder gleich dem Wert der Instanz ist."""
return MyNumber(math.floor(self.value))
__ceil__
Die __ceil__-Magie-Methode definiert, wie die Deckenfunktion verhalten soll. Wenn Sie die math.ceil()-Funktion auf einer Instanz Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __ceil__(self) -> 'MyNumber':
"""Gibt die kleinste ganze Zahl zurück, die größer oder gleich dem Wert der Instanz ist."""
return MyNumber(math.ceil(self.value))
Beispiel: Verwendung der eindeutigen Operatoren
Jetzt, da wir die eindeutigen Operatoren für unsere MyNumber-Klasse definiert haben, schauen wir uns an, wie sie in unary_example.py funktionieren:
import math
from number import MyNumber
## Erstellen Sie ein neues MyNumber-Objekt
a = MyNumber(5)
## Verwenden Sie die __neg__-Methode mit der print-Funktion
print(f'{a.value=}, {-a.value=}') ## Ausgabe: a.value=5, -a.value=-5
## Erstellen Sie ein weiteres neues MyNumber-Objekt
a = MyNumber(-5)
## Verwenden Sie die __abs__-Methode mit der print-Funktion
print(f'{a.value=}, {abs(a).value=}') ## Ausgabe: a.value=-5, abs(a).value=5
## Erstellen Sie das dritte neue MyNumber-Objekt
a = MyNumber(5.678)
## Verwenden Sie die __round__-Methode mit der print-Funktion
print(f'{a.value=}, {round(a, 2).value=}') ## Ausgabe: a.value=5.678, round(a, 2).value=5.68
## Verwenden Sie die __floor__-Methode mit der print-Funktion
print(f'{a.value=}, {math.floor(a).value=}') ## Ausgabe: a.value=5.678, math.floor(a).value=5
## Verwenden Sie die __ceil__-Methode mit der print-Funktion
print(f'{a.value=}, {math.ceil(a).value=}') ## Ausgabe: a.value=5.678, math.ceil(a).value=6
Geben Sie dann den folgenden Befehl in der Konsole ein, um das Skript auszuführen.
python unary_example.py
Binäre Operatoren
Binäre Operationen sind Operationen, die zwei Operanden beinhalten, wie arithmetische Operationen wie Addition, Subtraktion, Multiplikation und Division, sowie Vergleichsoperationen wie Gleichheit, Ungleichheit, kleiner als, größer als usw.
__add__
Die __add__-Magie-Methode definiert, wie die Additionoperation verhalten soll. Wenn Sie den +-Operator auf Instanzen Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __add__(self, other: 'MyNumber') -> 'MyNumber':
"""Gibt die Summe des Wertes der Instanz und des Wertes der anderen Instanz zurück."""
return MyNumber(self.value + other.value)
__sub__
Die __sub__-Magie-Methode definiert, wie die Subtraktionsoperation verhalten soll. Wenn Sie den --Operator auf Instanzen Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __sub__(self, other: 'MyNumber') -> 'MyNumber':
"""Gibt die Differenz des Wertes der Instanz und des Wertes der anderen Instanz zurück."""
return MyNumber(self.value - other.value)
__mul__
Die __mul__-Magie-Methode definiert, wie die Multiplikationsoperation verhalten soll. Wenn Sie den *-Operator auf Instanzen Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __mul__(self, other: 'MyNumber') -> 'MyNumber':
"""Gibt das Produkt des Wertes der Instanz und des Wertes der anderen Instanz zurück."""
return MyNumber(self.value * other.value)
__truediv__
Die __truediv__-Magie-Methode definiert, wie die echte Divisionoperation verhalten soll. Wenn Sie den /-Operator auf Instanzen Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __truediv__(self, other: 'MyNumber') -> 'MyNumber':
"""Gibt das Ergebnis der Division des Wertes der Instanz durch den Wert der anderen Instanz zurück."""
return MyNumber(self.value / other.value)
__floordiv__
Die __floordiv__-Magie-Methode definiert, wie die Ganzzahldivisionoperation verhalten soll. Wenn Sie den //-Operator auf Instanzen Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __floordiv__(self, other: 'MyNumber') -> 'MyNumber':
"""Gibt die größte ganze Zahl zurück, die kleiner oder gleich dem Ergebnis der Division des Wertes der Instanz durch den Wert der anderen Instanz ist."""
return MyNumber(self.value // other.value)
__mod__
Die __mod__-Magie-Methode definiert, wie die Modulo-Operation verhalten soll. Wenn Sie den %-Operator auf Instanzen Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __mod__(self, other: 'MyNumber') -> 'MyNumber':
"""Gibt den Rest der Division des Wertes der Instanz durch den Wert der anderen Instanz zurück."""
return MyNumber(self.value % other.value)
__pow__
Die __pow__-Magie-Methode definiert, wie die Potenzoperation verhalten soll. Wenn Sie den **-Operator oder die pow()-Funktion auf Instanzen Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __pow__(self, other: 'MyNumber') -> 'MyNumber':
"""Gibt den Wert der Instanz hoch zur Potenz des Wertes der anderen Instanz zurück."""
return MyNumber(self.value ** other.value)
Beispiel: Verwendung der binären Operatoren
Jetzt, da wir die binären Operatoren für unsere MyNumber-Klasse definiert haben, schauen wir uns an, wie sie in binary_example.py funktionieren:
from number import MyNumber
## Erstellen Sie zwei neue MyNumber-Objekte
a = MyNumber(5)
b = MyNumber(3)
print(f'{a.value=}, {b.value=}') ## Ausgabe: a.value=5, b.value=3
## Verwenden Sie die __add__-Methode mit der print-Funktion
print(f'{(a+b).value=}') ## Ausgabe: (a+b).value=8
## Verwenden Sie die __sub__-Methode mit der print-Funktion
print(f'{(a-b).value=}') ## Ausgabe: (a-b).value=2
## Verwenden Sie die __mul__-Methode mit der print-Funktion
print(f'{(a*b).value=}') ## Ausgabe: (a*b).value=15
## Verwenden Sie die __truediv__-Methode mit der print-Funktion
print(f'{(a/b).value=}') ## Ausgabe: (a/b).value=1.6666666666666667
## Verwenden Sie die __floordiv__-Methode mit der print-Funktion
print(f'{(a//b).value=}') ## Ausgabe: (a//b).value=1
## Verwenden Sie die __mod__-Methode mit der print-Funktion
print(f'{(a%b).value=}') ## Ausgabe: (a%b).value=2
## Verwenden Sie die __pow__-Methode mit der print-Funktion
print(f'{(a**b).value=}') ## Ausgabe: (a**b).value=125
Geben Sie dann den folgenden Befehl in der Konsole ein, um das Skript auszuführen.
python binary_example.py
In-place-Operationen
In-place-Operationen sind Operationen, die den Wert eines Objekts direkt verändern, ohne ein neues Objekt zu erstellen. Sie werden durch die erweiterten Zuweisungsoperatoren wie +=, -=, *=, /= usw. angegeben.
Wenn der In-place-Operator für eine Python-Klasse nicht definiert ist, wird der binäre Operator stattdessen verwendet, wenn eine In-place-Operation versucht wird.
Es gibt ein Beispiel in inplace_example1.py, ändern Sie die binären Operatoren in In-place-Operatoren:
from number import MyNumber
## Erstellen Sie zwei neue MyNumber-Objekte
a = MyNumber(5)
b = MyNumber(3)
print(f'{a.value=}, {b.value=}') ## Ausgabe: a.value=5, b.value=3
a += b
## Verwenden Sie die __add__-Methode mit der print-Funktion
print(f'after a+=b: {a.value=}') ## Ausgabe:after a+=b: (a+b).value=8
Um das Beispiel auszuführen, geben Sie folgenden Befehl in der Konsole ein:
python inplace_example1.py
Das Ergebnis zeigt, dass die __add__-Methode verwendet wurde, als die +=-Operation versucht wurde.
Dann implementieren wir die In-place-Operationen in MyNumber, und ihr Verhalten mit den entsprechenden binären Operatoren wird etwas unterschiedlich sein.
__iadd__
Die __iadd__-Magie-Methode definiert, wie die In-place-Additionoperation verhalten soll. Wenn Sie den +=-Operator auf Instanzen Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __iadd__(self, other: 'MyNumber') -> 'MyNumber':
"""Addiert den Wert der anderen Instanz in-place zum Wert der Instanz."""
print(f'input: {self.value=}, {other.value=}')
self.value += other.value
print(f'after +=: {self.value=}')
return self
__isub__
Die __isub__-Magie-Methode definiert, wie die In-place-Subtraktionoperation verhalten soll. Wenn Sie den -=-Operator auf Instanzen Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __isub__(self, other: 'MyNumber') -> 'MyNumber':
"""Subtrahiert den Wert der anderen Instanz in-place vom Wert der Instanz."""
print(f'input: {self.value=}, {other.value=}')
self.value -= other.value
print(f'after -=: {self.value=}')
return self
__imul__
Die __imul__-Magie-Methode definiert, wie die In-place-Multiplikationoperation verhalten soll. Wenn Sie den *=-Operator auf Instanzen Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __imul__(self, other: 'MyNumber') -> 'MyNumber':
"""Multipliziert den Wert der Instanz in-place mit dem Wert der anderen Instanz."""
print(f'input: {self.value=}, {other.value=}')
self.value *= other.value
print(f'after *=: {self.value=}')
return self
__itruediv__
Die __itruediv__-Magie-Methode definiert, wie die In-place-echte-Divisionoperation verhalten soll. Wenn Sie den /=-Operator auf Instanzen Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __itruediv__(self, other: 'MyNumber') -> 'MyNumber':
"""Teilt den Wert der Instanz in-place durch den Wert der anderen Instanz."""
print(f'input: {self.value=}, {other.value=}')
self.value /= other.value
print(f'after /=: {self.value=}')
return self
__ifloordiv__
Die __ifloordiv__-Magie-Methode definiert, wie die In-place-Ganzzahldivisionoperation verhalten soll. Wenn Sie den //=-Operator auf Instanzen Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __ifloordiv__(self, other: 'MyNumber') -> 'MyNumber':
"""Führt eine In-place-Ganzzahldivision des Wertes der Instanz durch den Wert der anderen Instanz durch."""
print(f'input: {self.value=}, {other.value=}')
self.value //= other.value
print(f'after //=: {self.value=}')
return self
__imod__
Die __imod__-Magie-Methode definiert, wie die In-place-Modulo-Operation verhalten soll. Wenn Sie den %=-Operator auf Instanzen Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __imod__(self, other: 'MyNumber') -> 'MyNumber':
"""Führt eine In-place-Modulo-Operation auf dem Wert der Instanz durch den Wert der anderen Instanz durch."""
print(f'input: {self.value=}, {other.value=}')
self.value %= other.value
print(f'after %=: {self.value=}')
return self
__ipow__
Die __ipow__-Magie-Methode definiert, wie die In-place-Potenz-Operation verhalten soll. Wenn Sie den **=-Operator auf Instanzen Ihrer Klasse verwenden, wird diese Methode aufgerufen.
#... (vorheriger Code in number.py)
def __ipow__(self, other: 'MyNumber') -> 'MyNumber':
"""Potenziert den Wert der Instanz in-place mit der Potenz des Wertes der anderen Instanz."""
print(f'input: {self.value=}, {other.value=}')
self.value **= other.value
print(f'after **=: {self.value=}')
return self
Beispiel: Verwendung der In-place-Operationen
Jetzt, da wir die In-place-Operatoren für unsere MyNumber-Klasse definiert haben, schauen wir uns an, wie sie in inplace_example2.py funktionieren:
from number import MyNumber
## Erstellen Sie ein neues MyNumber-Objekt
a = MyNumber(13)
## Verwenden Sie die __iadd__-Methode
a += MyNumber(5)
## Ausgabe:
## input: self.value=13, other.value=5
## after +=: self.value=18
## Verwenden Sie die __isub__-Methode
a -= MyNumber(5)
## Ausgabe:
## input: self.value=18, other.value=5
## after -=: self.value=13
## Verwenden Sie die __imul__-Methode
a *= MyNumber(5)
## Ausgabe:
## input: self.value=13, other.value=5
## after *=: self.value=65
## Verwenden Sie die __itruediv__-Methode
a /= MyNumber(5)
## Ausgabe:
## input: self.value=65, other.value=5
## after /=: self.value=13.0
## Verwenden Sie die __ifloordiv__-Methode
a //= MyNumber(2)
## Ausgabe:
## input: self.value=13.0, other.value=2
## after //=: self.value=6.0
## Verwenden Sie die __imod__-Methode
a %= MyNumber(4)
## Ausgabe:
## input: self.value=6.0, other.value=4
## after %=: self.value=2.0
## Verwenden Sie die __ipow__-Methode
a **= MyNumber(3)
## Ausgabe:
## input: self.value=2.0, other.value=3
## after **=: self.value=8.0
Geben Sie dann folgenden Befehl in der Konsole ein, um das Skript auszuführen.
python inplace_example2.py
Zusammenfassung
In diesem Tutorial haben wir uns mit Python-Magie-Methoden beschäftigt, die mit numerischen Operationen zusammenhängen. Diese Methoden ermöglichen es Ihnen, benutzerdefiniertes Verhalten für Ihre Klassen zu definieren, wenn Sie mit verschiedenen Arten von numerischen Operationen interagieren. Wir haben uns mit eindeutigen Operatoren, binären Operatoren und In-place-Operationen befasst und dabei gelernt, wie jede Magie-Methode implementiert wird.
Indem Sie diese Magie-Methoden in Ihren benutzerdefinierten Klassen implementieren, können Sie intuitive und leicht zu verwendende Objekte erstellen, die nahtlos mit standardmäßigen Python-Operationen zusammenarbeiten. Dies verbessert nicht nur die Lesbarkeit Ihres Codes, sondern auch seine Wartbarkeit und Benutzerfreundlichkeit.
Wenn Sie Ihre Python-Fähigkeiten weiterentwickeln, denken Sie daran, mit anderen Magie-Methoden zu experimentieren, um das Verhalten Ihrer Klassen weiter anzupassen und noch leistungsfähigere Abstraktionen zu schaffen.



