Über das Tippen von Enten :
Die Typisierung von Enten wird dadurch unterstützt, dass gewohnheitsmäßig nicht auf die Art der Argumente in Methoden- und Funktionskörpern geprüft wird. Dabei wird auf Dokumentation, klaren Code und Tests zurückgegriffen, um die korrekte Verwendung sicherzustellen.
Informationen zur Argumentvalidierung (EAFP: Es ist einfacher, um Vergebung zu bitten als um Erlaubnis). Ein angepasstes Beispiel von hier :
... es wird als pythonischer angesehen:
def my_method(self, key):
try:
value = self.a_dict[member]
except TypeError:
# do something else
Dies bedeutet, dass jeder andere Benutzer Ihres Codes kein echtes Wörterbuch oder keine echte Unterklasse verwenden muss. Er kann jedes Objekt verwenden, das die Zuordnungsschnittstelle implementiert.
Leider ist es in der Praxis nicht so einfach. Was ist, wenn das Mitglied im obigen Beispiel eine Ganzzahl sein könnte? Ganzzahlen sind unveränderlich - daher ist es durchaus sinnvoll, sie als Wörterbuchschlüssel zu verwenden. Sie werden jedoch auch zum Indizieren von Objekten vom Typ Sequenz verwendet. Wenn das Mitglied zufällig eine Ganzzahl ist, können in Beispiel 2 Listen und Zeichenfolgen sowie Wörterbücher durchgelassen werden.
Über durchsetzungsfähige Programmierung:
Behauptungen sind eine systematische Methode, um zu überprüfen, ob der interne Status eines Programms dem vom Programmierer erwarteten entspricht, mit dem Ziel, Fehler zu erkennen. Insbesondere sind sie gut geeignet, um falsche Annahmen zu erfassen, die beim Schreiben des Codes getroffen wurden, oder um eine Schnittstelle durch einen anderen Programmierer zu missbrauchen. Darüber hinaus können sie in gewissem Umfang als Inline-Dokumentation dienen, indem die Annahmen des Programmierers offensichtlich gemacht werden. ("Explizit ist besser als implizit.")
Die genannten Konzepte stehen manchmal in Konflikt, daher zähle ich bei der Auswahl auf die folgenden Faktoren, wenn ich überhaupt keine Datenvalidierung durchführe, eine starke Validierung durchführe oder Asserts verwende:
Starke Validierung. Mit starker Validierung meine ich das Auslösen einer benutzerdefinierten Ausnahme (
ApiError
zum Beispiel). Wenn meine Funktion / Methode Teil einer öffentlichen API ist, ist es besser, das Argument zu überprüfen, um eine gute Fehlermeldung über einen unerwarteten Typ anzuzeigen. Mit der Überprüfung des Typs meine ich nicht nur die Verwendungisinstance
, sondern auch, ob das übergebene Objekt die erforderliche Schnittstelle unterstützt (Ententypisierung). Während ich die API dokumentiere und den erwarteten Typ spezifiziere und der Benutzer meine Funktion möglicherweise auf unerwartete Weise verwenden möchte, fühle ich mich sicherer, wenn ich die Annahmen überprüfe. Normalerweise verwende ichisinstance
und wenn ich später andere Typen oder Enten unterstützen möchte, ändere ich die Validierungslogik.Durchsetzungsfähige Programmierung. Wenn mein Code neu ist, verwende ich viel Asserts. Was raten Sie dazu? Entfernen Sie später Asserts aus dem Code?
Wenn meine Funktion / Methode nicht Teil einer API ist, aber einige ihrer Argumente an einen anderen Code weiterleitet, der nicht von mir geschrieben, studiert oder getestet wurde, mache ich viele Asserts gemäß der aufgerufenen Schnittstelle. Meine Logik dahinter - scheitern Sie besser in meinem Code, dann irgendwo 10 Ebenen tiefer im Stacktrace mit unverständlichem Fehler, der dazu zwingt, viel zu debuggen und die Behauptung später trotzdem zu meinem Code hinzuzufügen.
Kommentare und Ratschläge zur Verwendung oder Nichtverwendung der Typ- / Wertvalidierung, behauptet? Entschuldigung für die nicht beste Formulierung der Frage.
Betrachten Sie beispielsweise die folgende Funktion, bei der Customer
es sich um ein deklaratives SQLAlchemy-Modell handelt:
def add_customer(self, customer):
"""Save new customer into the database.
@param customer: Customer instance, whose id is None
@return: merged into global session customer
"""
# no validation here at all
# let's hope SQLAlchemy session will break if `customer` is not a model instance
customer = self.session.add(customer)
self.session.commit()
return customer
Es gibt also mehrere Möglichkeiten, mit der Validierung umzugehen:
def add_customer(self, customer):
# this is an API method, so let's validate the input
if not isinstance(customer, Customer):
raise ApiError('Invalid type')
if customer.id is not None:
raise ApiError('id should be None')
customer = self.session.add(customer)
self.session.commit()
return customer
oder
def add_customer(self, customer):
# this is an internal method, but i want to be sure
# that it's a customer model instance
assert isinstance(customer, Customer), 'Achtung!'
assert customer.id is None
customer = self.session.add(customer)
self.session.commit()
return customer
Wann und warum sollten Sie diese im Zusammenhang mit der Eingabe von Enten, der Typprüfung und der Datenvalidierung verwenden?
quelle
Antworten:
Lassen Sie mich einige Leitprinzipien geben.
Prinzip Nr. 1. Wie unter http://docs.python.org/2/reference/simple_stmts.html beschrieben, kann der Leistungsaufwand für Asserts mit einer Befehlszeilenoption entfernt werden, während das Debuggen weiterhin möglich ist. Wenn die Leistung ein Problem darstellt, tun Sie dies. Lass die Behauptungen. (Aber tu nichts Wichtiges in den Behauptungen!)
Prinzip Nr. 2. Wenn Sie etwas behaupten und einen schwerwiegenden Fehler haben, verwenden Sie eine Bestätigung. Es ist absolut wertlos, etwas anderes zu tun. Wenn jemand das später ändern möchte, kann er Ihren Code ändern oder diesen Methodenaufruf vermeiden.
Prinzip Nr. 3. Verbieten Sie etwas nicht, nur weil Sie denken, dass es eine dumme Sache ist, dies zu tun. Was ist, wenn Ihre Methode Strings durchlässt? Wenn es funktioniert, funktioniert es.
Prinzip Nr. 4. Verbieten Sie Dinge, die Anzeichen für wahrscheinliche Fehler sind. Erwägen Sie beispielsweise, ein Wörterbuch mit Optionen zu erhalten. Wenn dieses Wörterbuch Dinge enthält, die keine gültigen Optionen sind, ist dies ein Zeichen dafür, dass jemand Ihre API nicht verstanden hat oder einen Tippfehler hatte. Wenn Sie das in die Luft jagen, ist es wahrscheinlicher, dass Sie einen Tippfehler bekommen, als dass Sie jemanden davon abhalten, etwas Vernünftiges zu tun.
Basierend auf den ersten beiden Prinzipien kann Ihre zweite Version weggeworfen werden. Welche der beiden anderen Sie bevorzugen, ist Geschmackssache. Was denkst du wahrscheinlicher? Dass jemand einen Nicht-Kunden weitergibt
add_customer
und die Dinge kaputt gehen (in diesem Fall wird Version 3 bevorzugt), oder dass jemand Ihren Kunden irgendwann durch ein Proxy-Objekt ersetzen möchte, das auf alle richtigen Methoden reagiert (In diesem Fall wird Version 1 bevorzugt).Persönlich habe ich beide Fehlermodi gesehen. Ich würde eher mit Version 1 aus dem allgemeinen Prinzip heraus gehen, dass ich faul bin und weniger tippe. (Auch diese Art von Fehler tritt normalerweise früher oder später auf ziemlich offensichtliche Weise auf. Und wenn ich ein Proxy-Objekt verwenden möchte, ärgere ich mich sehr über Leute, die mir die Hände gebunden haben.) Aber es gibt Programmierer, die ich respektiere würde den anderen Weg gehen.
quelle