Ü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?