Ich arbeite mit ganzen Zahltypen, also int oder long, und moechte die Verknüpfung 'a/b' oder 'a//b' umdefinieren, da für mich weder '/' noch '//' besonders geeignet ist. Es soll nie, wie beim derzeitigen Python, ein float ausgegeben werden. Falls bei der Teilung kein Rest entsteht soll ein type(a), also ein int oder long, ausgegeben werden; und falls ein Rest übrigbleibt, soll ein IntegerDivisionError gemeldet werden:
int(k*a) / k ---> int(a) oder IntegerDivisionError
long(k*a) / k ---> long(a) oder IntegerDivisionError
Fragen:
(1) Ist es möglich '/' für normale Zahlen zu überschreiben, oder muss ich Sonderklassen <echter_int> und <echter_long> dafür benutzen? Insbesondere, kann ich zum Beispiel sicherstellen, dass <echter_int> + <int> ---> <echter_int> gilt?
(2) Muss ich sämtliche Operationen, die unverändert bleiben sollen, neu definieren, oder lassen die sich einfach über Vererbung benutzen? Ich stelle fest, dass eingebaute Klassen wie int gar keine ECHTEN Objekte sind (sie haben zum Beispiel kein __dict__-Attribut wie jedes benutzerdefiniertes Objekt).
(3) Muss ich gro3e Performanz -Einbu3en erwarten?
Echte ganzzahlige Teilung
Code: Alles auswählen
In [1]: from __future__ import division
In [2]: 1.5 / 1.2
Out[2]: 1.25
In [3]: 1.5 // 1.2
Out[3]: 1.0
In [4]: 1.5 // 1
Out[4]: 1.0
In [5]: 1 // 1
Out[5]: 1
@Goswin: Am einfachsten ist es eine entsprechende Funktion zu schreiben und die statt der Division zu verwenden. Ungetestet:
Code: Alles auswählen
def my_div(a, b):
result, remainder = divmod(a, b)
if remainder:
raise ValueError('a (%r) not divisible by b (%r)' % (a, b))
return result
Zahliterale in Python sind nun mal vom Typ "int" bzw. "long". Nur weil du mal eben eine Klasse davon abgeleitet hast, definiert der Interpreter ja nicht gleich die Literaltypen um. Folglich musst du konsequent mit eigenen Objekten arbeiten. Dieser Ansatz ist höchst fehleranfällig. Vergisst du einmal, ein "int"-Objekt in deinen eigenen Typ zu konvertieren, so gibt das ja keinen Fehler, sondern ein falsches Ergebnis. Selbst mit vernünftigen Unittests ist das sehr schwer zu Debuggen.Goswin hat geschrieben:Fragen:
(1) Ist es möglich '/' für normale Zahlen zu überschreiben, oder muss ich Sonderklassen <echter_int> und <echter_long> dafür benutzen? Insbesondere, kann ich zum Beispiel sicherstellen, dass <echter_int> + <int> ---> <echter_int> gilt?
BlackJack's Ansatz ist da auf jeden Fall besser, nicht nur zwecks Fehlervermeidung, sondern auch, um deinen Code für andere besser lesbar zu machen. Ein Python-Programmierer erwartet von / und // nämlich klar definiertes Verhalten. Werden diese Operatoren jetzt überladen, dann erleichtert das nicht gerade das Verständnis von Berechnungen.
In Python ist alles außer Operatoren ein Objekt! Auch int oder long. Das fehlende __dict__ Attribut tut nichts zu Sache, folgende Klasse hat ebenfalls kein __dict__:(2) Muss ich sämtliche Operationen, die unverändert bleiben sollen, neu definieren, oder lassen die sich einfach über Vererbung benutzen? Ich stelle fest, dass eingebaute Klassen wie int gar keine ECHTEN Objekte sind (sie haben zum Beispiel kein __dict__-Attribut wie jedes benutzerdefiniertes Objekt).
Code: Alles auswählen
class Foo(object):
__slots__ = ['foo']
Das kommt ganz darauf an, was du in den überschriebenen Operator-Methode tatsächlich machst.(3) Muss ich gro3e Performanz -Einbu3en erwarten?