Ich habe float unterklassifiziert, um seine __str__() -Methode so zu ändern, dass sie mit einem Symbol endet (in meinem Fall €).

Die Eingabe wird gefiltert, um ein Symbol zu entfernen (in meinem Fall €).

class Euro(float):
    def __new__(cls, value):
        v = ''.join([_ for  _ in value if _ != '€' ])
        return super(Euro, cls).__new__(cls, v)

    def __str__(self):
        return f'{self} €'

Beim Drucken wird jedoch ein rekursiver Druckfehler angezeigt.

g = Euro('123.23 €')
print (g) 

Error:

Euro.py, line  __str__
    return f'{self} €'

 [Previous line repeated 329 more times]

RecursionError: maximum recursion depth exceeded
3
H Doucet 23 Feb. 2020 im 11:52

4 Antworten

Beste Antwort

Verwenden Sie keine Vererbung. a Euro ist keine Art von float, und Geld sollte aufgrund der Ungenauigkeit der Gleitkomma-Näherungen reeller Zahlen niemals mit float dargestellt werden.

Verwenden Sie stattdessen Zusammensetzung , um ein Attribut zu speichern, das die Anzahl der Euro darstellt, und verwenden Sie so etwas wie decimal.Decimal, um die Euro und Cent genau darzustellen.

from decimal import Decimal


class Euro:
    # In accordance with how to use super properly,
    # always accept and pass on unrecognized keyword arguments.
    def __init__(self, value, **kwargs):
        super().__init__(**kwargs)

        self.value = Decimal(value.strip('€'))

    def __str__(self):
        return f'{self.value} €'
1
chepner 23 Feb. 2020 im 16:58

Ich habe den folgenden Code erhalten:

from decimal import Decimal

class Euro:
    def __init__(self, value):
        if isinstance(value, str):
            value = value.strip(' €')
        self.value = Decimal(value)

    def __add__(self, other):
        return Euro(self.value + other.value)

    def __sub__(self,other):
        return Euro(self.value - other.value)

    def __str__(self):
        return f'{self.value} €'

Ich sehe keine Notwendigkeit für eine Unterklasse. Ich habe Unterstützung für +/- Operatoren hinzugefügt, die ein Euro-Objekt zurückgeben.

Das Ergebnis ist :

g = Euro(1.00)
h = Euro('10.00 €')

print (h+g) # --> 11.00 €
print (h-g) # -->  9.00 €
0
H Doucet 25 Feb. 2020 im 07:06

Betrachten Sie den Code,

def __str__(self):
    return f'{self} €'

Wenn Sie nun print(g) aufrufen, geschieht tatsächlich, dass print(g) die __str__ -Methode von Euro aufruft, die f'{self} €' zurückgibt, wie sich self bezieht In der Instanz von Euro selbst werden die __str__ -Methode von Euro weiter aufgerufen, und diese Rekursion wird fortgesetzt, bis der Stapelüberlauf erfolgt.

Um dieses Problem zu beheben, müssen Sie sicherstellen, dass keine Rekursion auftritt. Sie können dies auf folgende Weise erreichen:

class Euro(float):
    def __new__(self, value):
        self.value =  "".join([_ for  _ in value if _ != '€' and _ != " " ])
        return float.__new__(self, self.value)

    def __str__(self):
        return f'{self.value} €' # or return super().__str__() + ' €'

Wenn Sie jetzt print(g) aufrufen, wird wie erwartet 123.23 € zurückgegeben.

Hoffe das hilft!

0
Shubham Sharma 23 Feb. 2020 im 09:30

Verwenden Sie super(), um die übergeordnete Methode aufzurufen und den Rekursionsfehler zu vermeiden.

def __str__(self):
    return super().__str__() + ' €'


>>> g = Euro('123.23 €')
>>> print(g)
123.23 €
2
alec 23 Feb. 2020 im 09:02