Wird es als schlechte Form angesehen, Ausnahmen innerhalb zu erheben __init__
? Wenn ja, wie wird dann ein Fehler ausgegeben, wenn bestimmte Klassenvariablen als None
oder von falschem Typ initialisiert werden ?
Wird es als schlechte Form angesehen, Ausnahmen innerhalb zu erheben __init__
? Wenn ja, wie wird dann ein Fehler ausgegeben, wenn bestimmte Klassenvariablen als None
oder von falschem Typ initialisiert werden ?
Antworten:
Ausnahmen innerhalb zu erheben __init__()
ist absolut in Ordnung. Es gibt keine andere gute Möglichkeit, eine Fehlerbedingung innerhalb eines Konstruktors anzuzeigen, und es gibt viele hundert Beispiele in der Standardbibliothek, bei denen das Erstellen eines Objekts eine Ausnahme auslösen kann.
Die Fehlerklasse, die ausgelöst werden soll, liegt natürlich bei Ihnen. ValueError
ist am besten, wenn dem Konstruktor ein ungültiger Parameter übergeben wurde.
ValueError
und TypeError
.
__init__
Ich möchte nur darauf hinweisen, dass dies nicht der Konstruktor, sondern der Intializer ist. Vielleicht möchten Sie die Zeile bearbeiten. Es gibt keine andere gute Möglichkeit, eine Fehlerbedingung innerhalb eines Konstruktors anzuzeigen.
Es ist wahr, dass der einzig richtige Weg, um einen Fehler in einem Konstruktor anzuzeigen, darin besteht, eine Ausnahme auszulösen. Aus diesem Grund wird in C ++ und anderen objektorientierten Sprachen, die unter Berücksichtigung der Ausnahmesicherheit entwickelt wurden, der Destruktor nicht aufgerufen, wenn im Konstruktor eines Objekts eine Ausnahme ausgelöst wird (was bedeutet, dass die Initialisierung des Objekts unvollständig ist). Dies ist in Skriptsprachen wie Python häufig nicht der Fall. Der folgende Code löst beispielsweise einen AttributeError aus, wenn socket.connect () fehlschlägt:
class NetworkInterface:
def __init__(self, address)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect(address)
self.stream = self.socket.makefile()
def __del__(self)
self.stream.close()
self.socket.close()
Der Grund ist, dass der Destruktor des unvollständigen Objekts aufgerufen wird, nachdem der Verbindungsversuch fehlgeschlagen ist, bevor das Stream-Attribut initialisiert wurde. Sie sollten es nicht vermeiden, Ausnahmen von Konstruktoren auszulösen. Ich sage nur, dass es schwierig ist, vollständig ausnahmesicheren Code in Python zu schreiben. Einige Python-Entwickler vermeiden die Verwendung von Destruktoren insgesamt, aber das ist eine Frage einer anderen Debatte.
__del__
weil er schlecht geschrieben ist. Sie hätten genau das gleiche Problem, wenn Sie es this->p_socket->close()
in einem Destruktor in C ++ getan hätten . In C ++ würden Sie das nicht tun - Sie würden das Mitgliedsobjekt sich selbst zerstören lassen. Machen Sie dasselbe in Python.
Ich sehe keinen Grund, warum es eine schlechte Form sein sollte.
Im Gegenteil, eine der Ausnahmen ist bekannt dafür, dass Fehlercodes im Gegensatz zur Rückgabe von Fehlercodes normalerweise nicht von Konstruktoren zurückgegeben werden können. Zumindest in Sprachen wie C ++ ist das Auslösen von Ausnahmen die einzige Möglichkeit, Fehler zu signalisieren.
Ich stimme all dem zu.
Es gibt wirklich keinen anderen Weg, um zu signalisieren, dass bei der Initialisierung eines Objekts ein Fehler aufgetreten ist, als eine Ausnahme auszulösen.
In den meisten Programmklassen, in denen der Status einer Klasse vollständig von den Eingaben in diese Klasse abhängt, können wir erwarten, dass eine Art ValueError oder TypeError ausgelöst wird.
Klassen mit Nebenwirkungen (z. B. solche, die Netzwerke oder Grafiken ausführen) können einen Fehler in init auslösen, wenn (zum Beispiel) das Netzwerkgerät nicht verfügbar ist oder das Canvas-Objekt nicht beschrieben werden kann. Das klingt für mich sinnvoll, weil Sie oft so schnell wie möglich über Fehlerzustände informiert werden möchten.