Was ist die Verwendung von "assert" in Python?


Antworten:


1082

Die assertAnweisung existiert in fast jeder Programmiersprache. Es hilft dabei, Probleme frühzeitig in Ihrem Programm zu erkennen, wenn die Ursache klar ist, und nicht später als Nebeneffekt einer anderen Operation.

Wenn Sie das tun...

assert condition

... Sie weisen das Programm an, diese Bedingung zu testen und sofort einen Fehler auszulösen, wenn die Bedingung falsch ist.

In Python entspricht dies in etwa:

if not condition:
    raise AssertionError()

Probieren Sie es in der Python-Shell aus:

>>> assert True # nothing happens
>>> assert False
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError

Zusicherungen können eine optionale Nachricht enthalten, die Sie beim Ausführen des Interpreters deaktivieren können.

So drucken Sie eine Nachricht, wenn die Zusicherung fehlschlägt:

assert False, "Oh no! This assertion failed!"

Verwenden Sie keine Klammern, um assertwie eine Funktion aufzurufen . Es ist eine Aussage. Wenn Sie dies tun, führen assert(condition, message)Sie das assertmit einem (condition, message)Tupel als erstem Parameter aus.

Wie zum Deaktivieren sie, beim Laufen pythonin optimierten Modus, wo __debug__ist False, werden assert - Anweisungen ignoriert. Übergeben Sie einfach die -OFlagge:

python -O script.py

Siehe hier für die entsprechende Dokumentation.


92
Nit: assert ist eine Aussage und keine Funktion. Und im Gegensatz zu Print ist es in Python 3 immer noch eine Aussage .
Bob Stein

2
@Chaine assert bedeutet "sicherstellen, dass * etwas" wahr ist ". Assert also a == 3 stellt sicher, dass a gleich 3 ist; wenn a nicht gleich 3 ist (dh a == 3 ist falsch), wird es einen Fehler
auslösen

5
Wenn ich nur das verwenden kann if not condition: raise AssertError(), warum sollte ich assert verwenden? Gibt es Bedingungen, unter denen die Behauptung besser ist als nur eine kürzere Form der if not conditionAussage?
Alpha_989

6
@ alpha_989 a) Es ist kürzer und besser lesbar. b) Sie können Assert-Anweisungen deaktivieren, wenn Sie den Interpreter ausführen (nicht so im Handbuch if). Lesen Sie die Dokumente für weitere Informationen :)
Slezica

9
Ich kann überhaupt nicht verstehen, wie diese Antwort so viele Stimmen bekommt, eigentlich antworten auch andere. Die Frage lautet "Was ist die Verwendung von" assert "in Python?", daher wird gefragt: wann zu verwenden ist oder genauer: wie lautet das Verwendungsszenario assert, aber nachdem ich alle Antworten gelesen habe, habe ich absolut nichts, was ich will!
Inshi

423

Achten Sie auf die Klammern. Wie oben erwähnt, handelt es sich in Python 3 assertimmer noch um eine Aussage . In Analogie print(..)zu kann man das gleiche auf extrapolieren assert(..)oder raise(..)Sie sollten es nicht.

Dies ist wichtig, weil:

assert(2 + 2 == 5, "Houston we've got a problem")

wird im Gegensatz zu nicht funktionieren

assert 2 + 2 == 5, "Houston we've got a problem"

Der Grund, warum der erste nicht funktioniert, ist der, der bool( (False, "Houston we've got a problem") )ausgewertet wird True.

In der Anweisung assert(False)handelt es sich lediglich um redundante Klammern False, die nach ihrem Inhalt ausgewertet werden. Aber mit assert(False,)den Klammern ist jetzt ein Tupel, und ein nicht leeres Tupel wird Truein einem booleschen Kontext ausgewertet .


18
Ich bin hierher gekommen, um genau diese Informationen über Parens und die folgende Nachricht zu suchen. Vielen Dank.
Superbeck

6
Aber assert (2 + 2 = 5), "Houston we've got a problem"sollte ok sein, ja?
SherylHohman

4
@SherylHohman Sie können auch versuchen, das selbst auszuführen und zu sehen, ob es funktioniert oder nicht
DarkCygnus

2
Vergessen Sie nicht, dass Benutzer häufig Klammern für die PEP 8-konforme implizite Zeilenfortsetzung verwenden. Vergessen Sie auch nicht, dass Tupel nicht durch Klammern, sondern durch das Vorhandensein des Kommas definiert werden (Tupel haben nichts mit Parens zu tun, außer für die Zwecke von Vorrang des Bedieners).
Cowbert

4
assert (2 + 2 = 5), "Houston we've got a problem"wird nicht funktionieren ... aber es hat nichts mit der assert-Anweisung zu tun, was in Ordnung ist. Ihr Zustand wird nicht funktionieren, weil es kein Zustand ist. Eine Sekunde fehlt =.
n1k31t4

133

Wie andere Antworten festgestellt haben, assertähnelt dies dem Auslösen einer Ausnahme, wenn eine bestimmte Bedingung nicht erfüllt ist. Ein wichtiger Unterschied besteht darin, dass Assert-Anweisungen ignoriert werden, wenn Sie Ihren Code mit der Optimierungsoption kompilieren -O. Die Dokumentation besagt, dass assert expressiondies besser als gleichwertig beschrieben werden kann

if __debug__:
   if not expression: raise AssertionError

Dies kann nützlich sein, wenn Sie Ihren Code gründlich testen und dann eine optimierte Version veröffentlichen möchten, wenn Sie froh sind, dass keiner Ihrer Assertionsfälle fehlschlägt. Wenn die Optimierung aktiviert ist, wird die __debug__Variable zu False und die Bedingungen werden nicht mehr ausgewertet. Diese Funktion kann Sie auch auffangen, wenn Sie sich auf die Behauptungen verlassen und nicht erkennen, dass sie verschwunden sind.


Bedeutet dies, dass eine bestimmte Variable oder korrekte Eingabe (gemäß dem Vertrag, durch den das Programm geschrieben wird) zum Absturz des Programms führen kann, wenn es vom Benutzer ausgeführt wird (vorausgesetzt, dass das Flag -O verwendet wird, wenn der Benutzer das ausführt) Programm), sollten Sie stattdessen die if Not Error: raise Exception(“ this is a error”)? Auf diese Weise zeigt das Programm immer noch die Fehlerquelle an, wenn der Benutzer sie
ausführt

Wenn Sie jedoch erwarten, dass das Programm aufgrund einer falschen Logik / Implementierung des Codes (jedoch nicht aufgrund einer vertraglichen Eingabe an den Benutzer des Programms) fehlerhaft sein könnte, sollten Sie die assertAnweisung verwenden? Hierbei wird davon ausgegangen, dass Sie bei der Freigabe des Programms für den Endbenutzer das Flag -O verwenden und somit davon ausgehen, dass alle Fehler behoben wurden. Daher ist jeder Fehler oder Programmabsturz auf eine vertraglich gültige Eingabe in das Programm zurückzuführen, die jedoch vom Programm nicht behandelt werden kann. Daher sollte es den Benutzer als solchen alarmieren.
Alpha_989

@ alpha_989 das ist genau richtig. Ich stelle mir Behauptungen gerne als Überprüfung der geistigen Gesundheit vor, die Ihnen als Entwickler nur helfen sollen, sicherzustellen, dass das, was Sie für wahr halten, tatsächlich wahr ist, während Sie sich entwickeln.
Christopher Shroba

52

Das Ziel einer Behauptung in Python ist es, Entwickler über nicht behebbare Fehler in einem Programm zu informieren .

Behauptungen sollen keine erwarteten Fehlerzustände wie "Datei nicht gefunden" anzeigen, bei denen ein Benutzer Korrekturmaßnahmen ergreifen (oder es einfach erneut versuchen) kann.

Eine andere Sichtweise ist, zu sagen, dass Behauptungen interne Selbstprüfungen in Ihrem Code sind. Sie funktionieren, indem sie einige Bedingungen in Ihrem Code als unmöglich deklarieren . Wenn diese Bedingungen nicht zutreffen, liegt ein Fehler im Programm vor.

Wenn Ihr Programm fehlerfrei ist, treten diese Bedingungen niemals auf. Aber wenn einer von ihnen tut das Programm auftreten wird mit einer Assertion Fehler abstürzen Sie genau zu sagen , die „unmöglich“ Zustand ausgelöst wurde. Dies macht es viel einfacher, Fehler in Ihren Programmen aufzuspüren und zu beheben.

Hier ist eine Zusammenfassung aus einem Tutorial zu Pythons Behauptungen, die ich geschrieben habe:

Die Assert-Anweisung von Python ist eine Debugging-Hilfe und kein Mechanismus zur Behandlung von Laufzeitfehlern. Das Ziel der Verwendung von Behauptungen besteht darin, Entwicklern zu ermöglichen, die wahrscheinliche Grundursache eines Fehlers schneller zu finden. Ein Assertionsfehler sollte niemals ausgelöst werden, es sei denn, Ihr Programm enthält einen Fehler.


Danke für den Artikel. Sehr hilfreich, um die assertAussage zu verstehen und wann man sie verwendet. Ich versuche, eine Reihe von Begriffen zu verstehen, die Sie in dem Artikel eingeführt haben.
Alpha_989

Ich dachte, ich würde die Kommentare hier posten, damit viel mehr Menschen von den Klarstellungen profitieren könnten. Entschuldigung, wenn die Fragen zu naiv sind.
Alpha_989

In Ihrem von Ihnen verlinkten Blog geben Sie ein Beispiel an, in dem Sie erwähnt haben, dass "assert 0 <= price <= product ['price']" korrekt ist, aber mit "assert user.is_admin ()" Administratorrechte zum Löschen haben muss '`und assert store.product_exists(product_id), 'Unknown product id'ist keine gute Praxis, denn wenn das Debugging deaktiviert ist , kann das Produkt userauch dann admingelöscht werden, wenn dies nicht der Fall ist. Betrachten Sie assert user.is_admin()als unrecoverableFehler? Warum ist das nicht ein self-check?
Alpha_989

Wenn Sie der Meinung sind, dass 'user.is_admin ()' eine Benutzereingabe ist und daher nicht in einer verwendet werden sollte assert statement, kann dies nicht priceauch als Benutzereingabe betrachtet werden? Warum betrachten Sie assert user.is_admin()als Datenvalidierung, aber nicht assert price?
Alpha_989

1
@LaryxDecidua Nein, Sie können es einfach auf meiner Website lesen, das Tutorial ist öffentlich verfügbar. Drücken Sie einfach die Escape-Taste oder klicken Sie auf das kleine "x" -Symbol, wenn Sie nicht an dem Newsletter interessiert sind. Hoffe das hilft :-)
dbader

51

Andere haben Ihnen bereits Links zur Dokumentation gegeben.

In einer interaktiven Shell können Sie Folgendes ausprobieren:

>>> assert 5 > 2
>>> assert 2 > 5
Traceback (most recent call last):
  File "<string>", line 1, in <fragment>
builtins.AssertionError:

Die erste Anweisung bewirkt nichts, während die zweite eine Ausnahme auslöst. Dies ist der erste Hinweis: Asserts sind nützlich, um Bedingungen zu überprüfen, die an einer bestimmten Position Ihres Codes wahr sein sollten (normalerweise der Anfang (Voraussetzungen) und das Ende einer Funktion (Nachbedingungen)).

Behauptungen sind tatsächlich stark an die vertragliche Programmierung gebunden, was eine sehr nützliche technische Praxis ist:

http://en.wikipedia.org/wiki/Design_by_contract .


Bedeutet das also, dass wir in einer Situation wie assert (2> 5) Code einchecken und Fehler auslösen können, sonst fahren wir fort?

20
Die Parens verlieren, behaupten ist keine Funktion.
Pillmuncher

2
Die Parens zu verlieren ist wichtiger als es scheint. Siehe unten .
Evgeni Sergeev

6
Assert geht tatsächlich (lange vor "Verträgen") auf Turing zurück, als er einen der frühesten Artikel darüber schrieb, wie Programmierer die ziemlich entmutigende Aufgabe angehen könnten, korrekte Programme zu erstellen. Das Finden dieses Papiers bleibt dem Leser als Übung, da alle Programmierer davon profitieren können, sich mit seiner Arbeit vertraut zu machen. :-) turingarchive.org
Ron Burk

17

Aus Dokumenten:

Assert statements are a convenient way to insert debugging assertions into a program

Hier können Sie mehr lesen: http://docs.python.org/release/2.5.2/ref/assert.html


Ich mag diesen Kommentar, da er nur erklärt, was es sehr deutlich ist. Meine Frage lautet: "Wenn ich einen richtigen Komponententest geschrieben habe, warum brauche ich dann eine Behauptung?" das Zeug läuft sowieso nicht in der Produktion.
dtc

17

Die assert-Anweisung hat zwei Formen.

Die einfache Form assert <expression>ist äquivalent zu

if __debug__:
    if not <expression>: raise AssertionError

Die erweiterte Form assert <expression1>, <expression2>entspricht

if __debug__:
    if not <expression1>: raise AssertionError, <expression2>

16

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. Siehe das folgende Beispiel.

>>> number = input('Enter a positive number:')
Enter a positive number:-1
>>> assert (number > 0), 'Only positive numbers are allowed!'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError: Only positive numbers are allowed!
>>> 

1
Außerdem können Behauptungen häufig in Unit-Test-Programmen verwendet werden. stackoverflow.com/questions/1383/what-is-unit-testing
Panofish

7

Hier ist ein einfaches Beispiel: Speichern Sie dies in einer Datei (sagen wir b.py).

def chkassert(num):
    assert type(num) == int


chkassert('a')

und das Ergebnis, wenn $python b.py

Traceback (most recent call last):
  File "b.py", line 5, in <module>
    chkassert('a')
  File "b.py", line 2, in chkassert
    assert type(num) == int
AssertionError

6

Wenn die Anweisung nach der Bestätigung wahr ist, wird das Programm fortgesetzt. Wenn die Anweisung nach der Bestätigung jedoch falsch ist, gibt das Programm einen Fehler aus. So einfach ist das.

z.B:

assert 1>0   #normal execution
assert 0>1   #Traceback (most recent call last):
             #File "<pyshell#11>", line 1, in <module>
             #assert 0>1
             #AssertionError

4

Die assertAnweisung existiert in fast jeder Programmiersprache. Es hilft dabei, Probleme frühzeitig in Ihrem Programm zu erkennen, wenn die Ursache klar ist, und nicht später als Nebeneffekt einer anderen Operation. Sie erwarten immer einen TrueZustand.

Wenn Sie so etwas tun wie:

assert condition

Sie weisen das Programm an, diese Bedingung zu testen und sofort einen Fehler auszulösen, wenn er falsch ist.

In Python entspricht der assertAusdruck :

if __debug__:
    if not <expression>: raise AssertionError

Mit dem erweiterten Ausdruck können Sie eine optionale Nachricht übergeben :

if __debug__:
    if not (expression_1): raise AssertionError(expression_2)

Probieren Sie es im Python-Interpreter aus:

>>> assert True # Nothing happens because the condition returns a True value.
>>> assert False # A traceback is triggered because this evaluation did not yield an expected value.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError

Es gibt einige Einschränkungen, die zu beachten sind, bevor sie hauptsächlich für diejenigen verwendet werden, die es für angebracht halten, zwischen den Anweisungen assertund ifumzuschalten. Das zu verwendende Ziel assertist gelegentlich, wenn das Programm eine Bedingung überprüft und einen Wert zurückgibt, der das Programm sofort stoppen soll, anstatt einen alternativen Weg zu finden, um den Fehler zu umgehen:

1. Klammern

Wie Sie vielleicht bemerkt haben, verwendet die assertAnweisung zwei Bedingungen. Verwenden Sie daher keine Klammern, um sie als offensichtliche Ratschläge zu verwenden. Wenn Sie Folgendes tun:

assert (condition, message)

Beispiel:

>>> assert (1==2, 1==1)
<stdin>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?

Sie werden das assertmit einem (condition, message)ausführen, das ein Tupel als ersten Parameter darstellt, und dies geschieht, weil ein nicht leeres Tupel in Python immer istTrue . Sie können dies jedoch problemlos separat tun:

assert (condition), "message"

Beispiel:

>>> assert (1==2), ("This condition returns a %s value.") % "False"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError: This condition returns a False value.

2. Debug-Zweck

Wenn Sie sich fragen, wann Sie die assertAnweisung verwenden sollen. Nehmen Sie ein Beispiel aus dem wirklichen Leben:

* Wenn Ihr Programm dazu neigt, jeden vom Benutzer eingegebenen Parameter oder was auch immer zu steuern:

def loremipsum(**kwargs):
    kwargs.pop('bar') # return 0 if "bar" isn't in parameter
    kwargs.setdefault('foo', type(self)) # returns `type(self)` value by default
    assert (len(kwargs) == 0), "unrecognized parameter passed in %s" % ', '.join(kwargs.keys())

* Ein anderer Fall betrifft die Mathematik, wenn 0 oder nicht positiv als Koeffizient oder Konstante für eine bestimmte Gleichung gilt:

def discount(item, percent):
    price = int(item['price'] * (1.0 - percent))
    print(price)
    assert (0 <= price <= item['price']),\
            "Discounted prices cannot be lower than 0 "\
            "and they cannot be higher than the original price."

    return price

* oder sogar ein einfaches Beispiel für eine boolesche Implementierung:

def true(a, b):
    assert (a == b), "False"
    return 1

def false(a, b):
    assert (a != b), "True"
    return 0

3. Datenverarbeitung oder Datenvalidierung

Es ist äußerst wichtig, sich nicht auf die assertAnweisung zu verlassen, um die Datenverarbeitung oder Datenvalidierung auszuführen, da diese Anweisung bei der Python-Initialisierung mit -Ooder als -OOFlag (dh als Wert 1, 2 bzw. 0 (als Standard)) oder als PYTHONOPTIMIZEUmgebungsvariable deaktiviert werden kann .

Wert 1:

* Asserts sind deaktiviert;

* Bytecode-Dateien werden mit der .pyoErweiterung anstelle von generiert .pyc.

* sys.flags.optimizewird auf 1 ( True) gesetzt;

* und __debug__ist auf gesetzt False;

Wert 2: Deaktiviert ein weiteres Element

* docstrings sind deaktiviert;

Daher ist die Verwendung der assertAnweisung zur Validierung einer Art erwarteter Daten äußerst gefährlich und impliziert sogar einige Sicherheitsprobleme. Wenn Sie dann eine Berechtigung validieren müssen, empfehle ich Ihnen raise AuthErrorstattdessen. Als vorbedingte Wirksamkeit assertwird a häufig von Programmierern in Bibliotheken oder Modulen verwendet, bei denen kein Benutzer direkt interagiert.


3

Wie im C2-Wiki kurz zusammengefasst :

Eine Zusicherung ist ein boolescher Ausdruck an einem bestimmten Punkt in einem Programm, der wahr ist, es sei denn, das Programm enthält einen Fehler.

Sie können eine assertAnweisung verwenden, um Ihr Verständnis des Codes an einem bestimmten Programmpunkt zu dokumentieren. Beispielsweise können Sie Annahmen oder Garantien zu Eingaben (Voraussetzungen), Programmstatus (Invarianten) oder Ausgaben (Nachbedingungen) dokumentieren.

Sollte Ihre Behauptung jemals fehlschlagen, ist dies eine Warnung für Sie (oder Ihren Nachfolger), dass Ihr Verständnis des Programms beim Schreiben falsch war und dass es wahrscheinlich einen Fehler enthält.

Für weitere Informationen hat John Regehr einen wunderbaren Blog-Beitrag über die Verwendung von Behauptungen , der auch für die Python- assertAnweisung gilt .


2

Wenn Sie jemals genau wissen möchten, was eine reservierte Funktion in Python tut, geben Sie ein help(enter_keyword)

Stellen Sie sicher, dass Sie ein reserviertes Schlüsselwort als Zeichenfolge eingeben, wenn Sie es eingeben.


2

Python Assert ist im Grunde eine Debugging-Hilfe, die die Bedingung für die interne Selbstprüfung Ihres Codes testet. Assert macht das Debuggen wirklich einfach, wenn Ihr Code in unmögliche Randfälle gerät. Überprüfen Sie diese unmöglichen Fälle.

Angenommen, es gibt eine Funktion zum Berechnen des Artikelpreises nach Rabatt:

def calculate_discount(price, discount):
    discounted_price = price - [discount*price]
    assert 0 <= discounted_price <= price
    return discounted_price

Hier kann discounted_price niemals kleiner als 0 und größer als der tatsächliche Preis sein. Wenn also die oben genannte Bedingung verletzt wird, löst Assert einen Assertion Error aus, der dem Entwickler hilft, zu erkennen, dass etwas Unmögliches passiert ist.

Ich hoffe es hilft :)


2
assertist in einem Debugging-Kontext nützlich, sollte jedoch nicht außerhalb eines Debugging-Kontexts verwendet werden.
FluxIX

2

Meine kurze Erklärung lautet:

  • assertwird ausgelöst, AssertionErrorwenn der Ausdruck falsch ist, andernfalls wird der Code einfach fortgesetzt, und wenn ein Komma vorhanden ist, wird es wie folgt lauten AssertionError: whatever after comma:raise AssertionError(whatever after comma)

Ein verwandtes Tutorial dazu:

https://www.tutorialspoint.com/python/assertions_in_python.htm


Die Antwort gibt an, wie ein verwendet wird assert, aber nicht, wann ein verwendet werden soll (oder nicht) assert. auch darauf hingewiesen , dass eine assertbehinderte sein kann , wenn __debug__heißt Falsesinnvoll wäre.
FluxIX

1

Wenn Sie in Pycharm assertzusammen mit zusammen isinstanceden Typ eines Objekts deklarieren, können Sie während des Codierens auf die Methoden und Attribute des übergeordneten Objekts zugreifen. Die automatische Vervollständigung erfolgt automatisch.

Angenommen, es self.object1.object2handelt sich um ein MyClassObjekt.

import MyClasss

def code_it(self):
    testObject = self.object1.object2 # at this point, program doesn't know that testObject  is a MyClass object yet
    assert isinstance(testObject , MyClasss) # now the program knows testObject is a MyClass object
    testObject.do_it() # from this point on, PyCharm will be able to auto-complete when you are working on testObject

0

Wie in anderen Antworten geschrieben, werden assertAnweisungen verwendet, um den Status des Programms an einem bestimmten Punkt zu überprüfen.

Ich werde nicht wiederholen, was über zugehörige Nachrichten, Klammern oder -OOptionen und __debug__Konstanten gesagt wurde . Überprüfen Sie auch das Dokument auf Informationen aus erster Hand. Ich werde mich auf Ihre Frage konzentrieren: Was nützt das assert? Genauer gesagt, wann (und wann nicht) sollte man verwenden assert?

Die assertAnweisungen sind nützlich, um ein Programm zu debuggen, es wird jedoch davon abgeraten, Benutzereingaben zu überprüfen. Ich verwende die folgende Faustregel: Behalte die Behauptungen bei, um zu erkennen, dass dies nicht passieren sollte . Eine Benutzereingabe ist möglicherweise falsch, z. B. ein zu kurzes Kennwort. Dies sollte jedoch nicht der Fall sein. Wenn der Durchmesser eines Kreises nicht doppelt so groß ist wie sein Radius, sollten Sie dies nicht tun .

Die meiner Meinung nach interessanteste Verwendung assertist inspiriert von der vertraglichen Programmierung, wie sie von B. Meyer in [Objektorientierte Softwarekonstruktion] ( https://www.eiffel.org/doc/eiffel/Object-Oriented_Software_Construction%) beschrieben wurde 2C_2nd_Edition ) und implementiert in der [Eiffel-Programmiersprache] ( https://en.wikipedia.org/wiki/Eiffel_(programming_language) ). Sie können die vertragliche Programmierung mit der assertAnweisung nicht vollständig emulieren , aber es ist interessant, die Absicht beizubehalten.

Hier ist ein Beispiel. Stellen Sie sich vor, Sie müssen eine headFunktion schreiben (wie die [ headFunktion in Haskell] ( http://www.zvon.org/other/haskell/Outputprelude/head_f.html )). Die Spezifikation, die Sie erhalten, lautet: "Wenn die Liste nicht leer ist, geben Sie das erste Element einer Liste zurück". Schauen Sie sich die folgenden Implementierungen an:

>>> def head1(xs): return xs[0]

Und

>>> def head2(xs):
...     if len(xs) > 0:
...         return xs[0]
...     else:
...         return None

(Ja, das kann geschrieben werden als return xs[0] if xs else None, aber das ist nicht der Punkt) .

Wenn die Liste nicht leer ist, haben beide Funktionen das gleiche Ergebnis und dieses Ergebnis ist korrekt:

>>> head1([1, 2, 3]) == head2([1, 2, 3]) == 1
True

Daher sind beide Implementierungen (ich hoffe) korrekt. Sie unterscheiden sich, wenn Sie versuchen, das Hauptelement einer leeren Liste zu übernehmen:

>>> head1([])
Traceback (most recent call last):
...
IndexError: list index out of range

Aber:

>>> head2([]) is None
True

Auch hier sind beide Implementierungen korrekt, da niemand eine leere Liste an diese Funktionen übergeben sollte (wir sind außerhalb der Spezifikation ). Das ist ein falscher Anruf, aber wenn Sie einen solchen Anruf tätigen, kann alles passieren. Eine Funktion löst eine Ausnahme aus, die andere gibt einen speziellen Wert zurück. Das Wichtigste ist: Wir können uns nicht auf dieses Verhalten verlassen . Wenn xsleer ist, funktioniert dies:

print(head2(xs))

Dies führt jedoch zum Absturz des Programms:

print(head1(xs))

Um einige Überraschungen zu vermeiden, möchte ich wissen, wann ich ein unerwartetes Argument an eine Funktion übergebe. Mit anderen Worten: Ich würde gerne wissen, wann das beobachtbare Verhalten nicht zuverlässig ist, da es von der Implementierung und nicht von der Spezifikation abhängt. Natürlich kann ich die Spezifikation lesen, aber Programmierer lesen die Dokumente nicht immer sorgfältig.

Stellen Sie sich vor, ich hätte eine Möglichkeit, die Spezifikation in den Code einzufügen, um den folgenden Effekt zu erzielen: Wenn ich gegen die Spezifikation verstoße, z. B. indem headich eine leere Liste an übergebe , erhalte ich eine Warnung. Das wäre eine große Hilfe, um ein korrektes (dh mit der Spezifikation konformes) Programm zu schreiben. Und hier assert kommt die Szene ins Spiel:

>>> def head1(xs):
...     assert len(xs) > 0, "The list must not be empty"
...     return xs[0]

Und

>>> def head2(xs):
...     assert len(xs) > 0, "The list must not be empty"
...     if len(xs) > 0:
...         return xs[0]
...     else:
...         return None

Jetzt haben wir:

>>> head1([])
Traceback (most recent call last):
...
AssertionError: The list must not be empty

Und:

>>> head2([])
Traceback (most recent call last):
...
AssertionError: The list must not be empty

Beachten Sie, dass head1ein AssertionError, nicht ein IndexError. Dies ist wichtig, da AssertionErrores sich nicht um einen Laufzeitfehler handelt, sondern um einen Verstoß gegen die Spezifikation. Ich wollte eine Warnung, erhalte aber eine Fehlermeldung. Glücklicherweise kann ich die Prüfung deaktivieren (mit der -OOption), jedoch auf eigenes Risiko. Ich werde es tun, ein Absturz ist wirklich teuer und hoffe auf das Beste. Stellen Sie sich vor, mein Programm ist in ein Raumschiff eingebettet, das durch ein Schwarzes Loch fährt. Ich werde Behauptungen deaktivieren und hoffe, dass das Programm robust genug ist, um nicht so lange wie möglich abzustürzen.

In diesem Beispiel ging es nur um Vorbedingungen, mit denen Sie assertNachbedingungen (Rückgabewert und / oder Status) und Invarianten (Status einer Klasse) überprüfen können . Beachten Sie, dass das Überprüfen von Nachbedingungen und Invarianten mit assertumständlich sein kann:

  • Für Nachbedingungen müssen Sie den Rückgabewert einer Variablen zuweisen und möglicherweise den Anfangszustand des Objekts speichern, wenn Sie mit einer Methode arbeiten.
  • Für Invarianten müssen Sie den Status vor und nach einem Methodenaufruf überprüfen.

Sie werden nicht so anspruchsvoll sein wie Eiffel, aber Sie können die Gesamtqualität eines Programms verbessern.


Zusammenfassend ist die assertAussage ein bequemer Weg, um zu erkennen, dass dies nicht passieren sollte . Verstöße gegen die Spezifikation (z. B. Weitergabe einer leeren Liste an head) sind erstklassig. Dies sollte in Situationen nicht vorkommen. Während die assertAnweisung verwendet werden kann, um unerwartete Situationen zu erkennen, ist dies eine privilegierte Möglichkeit, um sicherzustellen, dass die Spezifikation erfüllt wird. Sobald Sie assertAnweisungen in den Code eingefügt haben , um die Spezifikation darzustellen, können wir hoffen, dass Sie die Qualität des Programms verbessert haben, da falsche Argumente, falsche Rückgabewerte, falsche Zustände einer Klasse ... gemeldet werden.


-2

format: assert Ausdruck [, Argumente] Wenn assert auf eine Anweisung stößt, wertet Python den Ausdruck aus. Wenn die Anweisung nicht wahr ist, wird eine Ausnahme ausgelöst (assertionError). Wenn die Zusicherung fehlschlägt, verwendet Python ArgumentExpression als Argument für den AssertionError. AssertionError-Ausnahmen können wie jede andere Ausnahme mit der try-exception-Anweisung abgefangen und behandelt werden. Wenn sie jedoch nicht behandelt werden, wird das Programm beendet und ein Traceback erstellt. Beispiel:

def KelvinToFahrenheit(Temperature):    
    assert (Temperature >= 0),"Colder than absolute zero!"    
    return ((Temperature-273)*1.8)+32    
print KelvinToFahrenheit(273)    
print int(KelvinToFahrenheit(505.78))    
print KelvinToFahrenheit(-5)    

Wenn der obige Code ausgeführt wird, wird das folgende Ergebnis erzeugt:

32.0
451
Traceback (most recent call last):    
  File "test.py", line 9, in <module>    
    print KelvinToFahrenheit(-5)    
  File "test.py", line 4, in KelvinToFahrenheit    
    assert (Temperature >= 0),"Colder than absolute zero!"    
AssertionError: Colder than absolute zero!    

-2
def getUser(self, id, Email):

    user_key = id and id or Email

    assert user_key

Kann verwendet werden, um sicherzustellen, dass Parameter im Funktionsaufruf übergeben werden.


1
Dies wird funktionieren, aber meines Wissens sollten Asserts nicht zum Überprüfen von Benutzereingaben verwendet werden, da sie zur Laufzeit deaktiviert werden können. Wenn Sie Benutzereingaben wirklich erzwingen oder validieren möchten, verwenden Sie die if not user_key: raise ValueError()letzten beiden
alpha_989

assertsollte nicht für die Eingabevalidierung verwendet werden, da entweder die Validierung entfernt wird, wenn dies der Fall __debug__ist False. Die Verwendung von Zusicherungen für Nicht-Debug-Zwecke kann dazu führen, dass Benutzer die resultierenden AssertionErrors abfangen , was das Debuggen schwieriger als weniger macht.
FluxIX

-4
>>>this_is_very_complex_function_result = 9
>>>c = this_is_very_complex_function_result
>>>test_us = (c < 4)

>>> #first we try without assert
>>>if test_us == True:
    print("YES! I am right!")
else:
    print("I am Wrong, but the program still RUNS!")

I am Wrong, but the program still RUNS!


>>> #now we try with assert
>>> assert test_us
Traceback (most recent call last):
  File "<pyshell#52>", line 1, in <module>
    assert test_us
AssertionError
>>> 

-4

Grundsätzlich bedeutet das Schlüsselwort assert, dass die Bedingung, wenn sie nicht erfüllt ist, durch einen Assertionerror andernfalls beispielsweise in Python fortgesetzt wird.

Code-1

a=5

b=6

assert a==b

AUSGABE:

assert a==b

AssertionError

Code-2

a=5

b=5

assert a==b

AUSGABE:

Process finished with exit code 0

2
Bitte formatieren Sie Ihren Code richtig. Wie verbessert sich dies gegenüber früheren Antworten?
c2huc2hu

Gibt es ein Problem in meiner Erklärung?
Ujjwal_bansal

Ihre Erklärung fügt den vorhandenen Antworten nichts hinzu, und die schlechte Grammatik erschwert das Lesen. Wenn Sie nach zu beantwortenden Fragen suchen, sollten Sie den neuen Fragen-Feed durchsuchen.
c2huc2hu

Die bereitgestellte Antwort beantwortet , wie eine verwenden assert, aber nicht antwortet , wenn zu verwenden (oder nicht verwenden) ein assert.
FluxIX
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.