Ihr Interesse an dem neuen Buch " Python Pro Secrets " hat uns überzeugt, dass die Geschichte der Python-Macken es verdient, fortgesetzt zu werden. Heute bieten wir an, ein kleines Tutorial zum Erstellen von benutzerdefinierten (im Text - Ihren eigenen) Ausnahmeklassen zu lesen. Der Autor fand es interessant, es ist schwierig, ihm zu widersprechen, dass der wichtigste Vorteil einer Ausnahme die Vollständigkeit und Klarheit der Fehlermeldung ist. Ein Teil des Codes aus dem Original besteht aus Bildern.
Willkommen bei Katze.
Erstellen Sie Ihre eigenen Fehlerklassen
Python bietet die Möglichkeit, eigene Ausnahmeklassen zu erstellen. Durch das Erstellen solcher Klassen können Sie das Design der Klassen in Ihrer Anwendung diversifizieren. Eine benutzerdefinierte Fehlerklasse kann Fehler protokollieren und das Objekt untersuchen. Wir definieren, was die Ausnahmeklasse tut, obwohl eine benutzerdefinierte Klasse normalerweise kaum mehr kann, als eine Nachricht anzuzeigen.
Natürlich ist der Fehlertyp selbst wichtig, und wir erstellen häufig eigene Fehlertypen, um auf eine bestimmte Situation hinzuweisen, die auf Python-Sprachebene normalerweise nicht behandelt wird. Auf diese Weise wissen Benutzer der Klasse genau, was passiert, wenn sie auf diesen Fehler stoßen.
Dieser Artikel ist in zwei Teile gegliedert. Zunächst definieren wir eine Ausnahmeklasse für sich. Anschließend zeigen wir, wie wir unsere eigenen Ausnahmeklassen in unsere Python-Programme integrieren können und wie wir so die Benutzerfreundlichkeit der von uns entworfenen Klassen verbessern können.
Benutzerdefinierte Ausnahmeklasse MyCustomError
Das Auslösen einer Ausnahme erfordert die Methoden
__init__()
und
__str__()
.
Beim Auslösen einer Ausnahme erstellen wir bereits eine Instanz der Ausnahme und zeigen sie gleichzeitig auf dem Bildschirm an. Schauen wir uns unsere unten gezeigte benutzerdefinierte Ausnahmeklasse genauer an.
Die obige MyCustomError Klasse hat zwei magische Methoden,
__init__
und
__str__
, die automatisch bei der Ausnahmebehandlung aufgerufen werden. Die Methode
Init
wird aufgerufen, wenn die Instanz erstellt wird, und die Methode
str
wird aufgerufen, wenn die Instanz angezeigt wird. Wenn eine Ausnahme ausgelöst wird, werden diese beiden Methoden daher normalerweise unmittelbar nacheinander aufgerufen. Die Python-Ausnahme-Throw-Anweisung versetzt ein Programm in einen Fehlerzustand.
In der Argumentliste der Methode
__init__
ist
*args
. Eine Komponente
*args
ist ein spezieller Mustervergleichsmodus, der in Funktionen und Methoden verwendet wird. Sie können mehrere Argumente übergeben und die übergebenen Argumente als Tupel speichern. Gleichzeitig können Sie jedoch überhaupt keine Argumente übergeben.
In unserem Fall können wir sagen, dass wenn
MyCustomError
Argumente an den Konstruktor übergeben wurden , wir das erste übergebene Argument nehmen und es einem Attribut
message
im Objekt zuweisen . Wenn keine Argumente übergeben wurden, wird dem Attribut
message
ein Wert zugewiesen
None
.
Im ersten Beispiel wird die Ausnahme
MyCustomError
ohne Argumente ausgelöst , also das Attribut
message
Diesem Objekt wird ein Wert zugewiesen
None
. Eine Methode wird aufgerufen
str
und zeigt die Meldung "MyCustomError-Meldung wurde ausgelöst" an.
Die Ausnahme
MyCustomError
wird ohne Argumente ausgelöst (Klammern sind leer). Mit anderen Worten, ein solches Objektdesign sieht nicht standardisiert aus. Dies ist jedoch nur syntaktische Unterstützung, die in Python beim Auslösen einer Ausnahme bereitgestellt wird.
Im zweiten Beispiel wird es
MyCustomError
mit einem String-Argument 'Wir haben ein Problem' übergeben. Es wird als Attribut des
message
Objekts festgelegt und als Fehlermeldung angezeigt, wenn eine Ausnahme ausgelöst wird.
Der Code für die MyCustomError-Ausnahmeklasse ist hier...
class MyCustomError(Exception):
def __init__(self, *args):
if args:
self.message = args[0]
else:
self.message = None
def __str__(self):
print('calling str')
if self.message:
return 'MyCustomError, {0} '.format(self.message)
else:
return 'MyCustomError has been raised'
# MyCustomError
raise MyCustomError('We have a problem')
CustomIntFloatDic-Klasse
Wir erstellen unser eigenes Wörterbuch, dessen Werte nur Ganzzahlen und Gleitkommazahlen sein können.
Lassen Sie uns zeigen, wie Sie Fehlerklassen einfach und sinnvoll in unsere eigenen Programme einfügen können. Zunächst werde ich ein leicht erfundenes Beispiel anbieten. In diesem fiktiven Beispiel werde ich mein eigenes Wörterbuch erstellen, das nur Ganzzahlen oder Gleitkommazahlen akzeptieren kann.
Wenn der Benutzer versucht, einen anderen Datentyp als Wert in diesem Wörterbuch anzugeben, wird eine Ausnahme ausgelöst. Diese Ausnahme bietet dem Benutzer nützliche Informationen zur Verwendung dieses Wörterbuchs. In unserem Fall informiert diese Nachricht den Benutzer direkt darüber, dass in diesem Wörterbuch nur Ganzzahlen oder Gleitkommazahlen als Werte angegeben werden können.
Beachten Sie beim Erstellen Ihres eigenen Wörterbuchs, dass es zwei Stellen gibt, an denen dem Wörterbuch Werte hinzugefügt werden können. Dies kann zum einen in der init-Methode beim Erstellen eines Objekts geschehen (zu diesem Zeitpunkt können dem Objekt bereits Schlüssel und Werte zugewiesen werden) und zum anderen beim Festlegen von Schlüsseln und Werten direkt im Wörterbuch. An beiden Stellen müssen Sie Code schreiben, um sicherzustellen, dass der Wert nur vom Typ
int
oder sein kann
float
.
Zuerst definiere ich die CustomIntFloatDict-Klasse, die von der integrierten Klasse erbt
dict
.
dict
in einer Liste von Argumenten übergeben, die in Klammern stehen und dem Klassennamen folgen
CustomIntFloatDict
.
Wenn eine Klasse instanziiert wird
CustomIntFloatDict
Darüber hinaus werden keine Argumente an die Schlüssel- und Wertparameter übergeben, sondern auf gesetzt
None
. Der Ausdruck wird
if
wie folgt interpretiert: Wenn entweder der Schlüssel gleich
None
oder der Wert gleich ist
None
, wird mit dem Objekt eine Methode aufgerufen
get_dict()
, die das Attribut
empty_dict
zurückgibt. Ein solches Attribut für ein Objekt zeigt auf eine leere Liste. Denken Sie daran, dass Klassenattribute für alle Instanzen der Klasse verfügbar sind.
Der Zweck dieser Klasse besteht darin, dem Benutzer das Übergeben einer Liste oder eines Tupels mit den darin enthaltenen Schlüsseln und Werten zu ermöglichen. Wenn der Benutzer eine Liste oder ein Tupel eingibt, das nach Schlüsseln und Werten sucht, werden diese beiden Aufzählungssätze mithilfe der Funktion verkettet
zip
die Python-Sprache. Eine verknüpfte Variable, die auf ein Objekt zeigt,
zip
ist iterierbar und Tupel können nicht entpackt werden. Durch Durchlaufen der Tupel überprüfe ich, ob val eine Instanz der Klasse
int
oder ist
float
. Wenn es
val
zu keiner dieser Klassen gehört, löse ich
IntFloatValueError
meine eigene Ausnahme und übergebe val als Argument.
IntFloatValueError-Ausnahmeklasse
Wenn eine Ausnahme ausgelöst wird,
IntFloatValueError
erstellen wir eine Instanz der Klasse
IntFloatValueError
und zeigen sie gleichzeitig auf dem Bildschirm an. Dies bedeutet, dass die magischen Methoden
init
und aufgerufen werden
str
.
Der Wert, der die ausgelöste Ausnahme verursacht hat, wird als Attribut für
value
die Klasse festgelegt
IntFloatValueError
. Beim Aufrufen der magic str-Methode erhält der Benutzer eine Fehlermeldung, dass der Wert
init
in
CustomIntFloatDict
ungültig ist. Der Benutzer weiß, was zu tun ist, um diesen Fehler zu beheben.
Ausnahmeklassen
IntFloatValueError
und
KeyValueConstructError
Wenn keine Ausnahme ausgelöst wird, also alle
val
vom verketteten Objekt sind vom Typ
int
oder
float
, dann werden sie mit gesetzt
__setitem__()
, und die Methode aus der übergeordneten Klasse erledigt alles für uns
dict
, wie unten gezeigt.
KeyValueConstructError-Klasse
Was passiert, wenn der Benutzer einen Typ eingibt, der keine Liste oder ein Tupel von Schlüsseln und Werten ist?
Auch dieses Beispiel ist etwas künstlich, aber es ist praktisch, Ihnen zu zeigen, wie Sie Ihre eigenen Ausnahmeklassen verwenden können.
Wenn der Benutzer die Schlüssel und Werte nicht als Liste oder Tupel angibt, wird eine Ausnahme ausgelöst
KeyValueConstructError
. Mit dieser Ausnahme soll der Benutzer darüber informiert werden, dass zum Schreiben von Schlüsseln und Werten in ein Objekt
CustomIntFloatDict
im
init
Klassenkonstruktor eine Liste oder ein Tupel angegeben werden muss
CustomIntFloatDict
.
Im obigen Beispiel als zweites Argument an den Konstruktor
init
viel wurde bestanden und eine Ausnahme wurde aus diesem Grund geworfen
KeyValueConstructError
. Der Vorteil der angezeigten Fehlermeldung besteht darin, dass die angezeigte Fehlermeldung den Benutzer darüber informiert, dass die einzufügenden Schlüssel und Werte entweder als Liste oder als Tupel gemeldet werden müssen.
Wenn eine Ausnahme ausgelöst wird, wird erneut eine KeyValueConstructError-Instanz erstellt und der Schlüssel und die Werte werden als Argumente an den KeyValueConstructError-Konstruktor übergeben. Sie werden als Werte der Schlüssel- und Wertattribute von KeyValueConstructError festgelegt und in der Methode __str__ verwendet, um eine aussagekräftige Fehlermeldung zu generieren, wenn die Nachricht auf dem Bildschirm angezeigt wird.
Außerdem füge ich sogar die Datentypen hinzu, die den dem Konstruktor hinzugefügten Objekten inhärent sind
init
- Ich mache das aus Gründen der Klarheit.
Festlegen von Schlüssel und Wert in CustomIntFloatDict
CustomIntFloatDict
erbt von
dict
. Dies bedeutet, dass es genau wie ein Wörterbuch funktioniert, außer an den Stellen, an denen wir sein Verhalten selektiv ändern möchten.
__setitem__
Ist eine magische Methode, die beim Festlegen eines Schlüssels und eines Werts in einem Wörterbuch aufgerufen wird. In unserer Implementierung
setitem
prüfen wir, ob der Wert vom Typ
int
oder ist
float
, und erst nach einer erfolgreichen Prüfung kann er im Wörterbuch festgelegt werden. Wenn die Prüfung fehlschlägt, können Sie die Ausnahmeklasse erneut verwenden
IntFloatValueError
. Hier können Sie sicherstellen, dass beim Versuch, eine Zeichenfolge
‘bad_value’
als Wert im Wörterbuch
test_4
festzulegen, eine Ausnahme angezeigt wird.
Der gesamte Code für dieses Tutorial wird unten angezeigt und auf Github veröffentlicht .
# , int float
class IntFloatValueError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return '{} is invalid input, CustomIntFloatDict can only accept ' \
'integers and floats as its values'.format(self.value)
class KeyValueContructError(Exception):
def __init__(self, key, value):
self.key = key
self.value = value
def __str__(self):
return 'keys and values need to be passed as either list or tuple' + '\n' + \
' {} is of type: '.format(self.key) + str(type(self.key)) + '\n' + \
' {} is of type: '.format(self.value) + str(type(self.value))
class CustomIntFloatDict(dict):
empty_dict = {}
def __init__(self, key=None, value=None):
if key is None or value is None:
self.get_dict()
elif not isinstance(key, (tuple, list,)) or not isinstance(value, (tuple, list)):
raise KeyValueContructError(key, value)
else:
zipped = zip(key, value)
for k, val in zipped:
if not isinstance(val, (int, float)):
raise IntFloatValueError(val)
dict.__setitem__(self, k, val)
def get_dict(self):
return self.empty_dict
def __setitem__(self, key, value):
if not isinstance(value, (int, float)):
raise IntFloatValueError(value)
return dict.__setitem__(self, key, value)
#
# test_1 = CustomIntFloatDict()
# print(test_1)
# test_2 = CustomIntFloatDict({'a', 'b'}, [1, 2])
# print(test_2)
# test_3 = CustomIntFloatDict(('x', 'y', 'z'), (10, 'twenty', 30))
# print(test_3)
# test_4 = CustomIntFloatDict(('x', 'y', 'z'), (10, 20, 30))
# print(test_4)
# test_4['r'] = 1.3
# print(test_4)
# test_4['key'] = 'bad_value'
Fazit
Wenn Sie Ihre eigenen Ausnahmen erstellen, wird die Arbeit mit der Klasse viel bequemer. Die Ausnahmeklasse sollte magische Methoden haben
init
und
str
dass werden automatisch während der Ausnahmebehandlung genannt. Es liegt ganz bei Ihnen, was Ihre eigene Ausnahmeklasse tun wird. Unter den gezeigten Methoden befinden sich diejenigen, die für die Inspektion eines Objekts und die Anzeige einer informativen Fehlermeldung auf dem Bildschirm verantwortlich sind.
Wie auch immer, Ausnahmeklassen erleichtern die Behandlung auftretender Fehler erheblich!