Python behaupten mit und ohne Klammer

103

Hier sind vier einfache Aufrufe zur Behauptung:

>>> assert 1==2
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AssertionError

>>> assert 1==2, "hi"
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AssertionError: hi

>>> assert(1==2)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AssertionError

>>> assert(1==2, "hi")

Beachten Sie, dass der letzte keinen Fehler auslöst. Was ist der Unterschied zwischen dem Aufruf von assert mit oder ohne Klammer, der dieses Verhalten verursacht? Meine Praxis besteht darin, Klammern zu verwenden, aber das oben Gesagte legt nahe, dass ich dies nicht tun sollte.

gaefan
quelle
Danke für die hilfreichen Antworten. Die Unterscheidung zwischen Schlüsselwörtern und integrierten Funktionen scheint subtil. Hier ist eine Liste von Schlüsselwörtern, für die ich annehme, dass Parens weggelassen werden
gaefan
2
Ein Unterschied besteht darin, dass Sie integrierte Funktionen neu definieren können, dies jedoch nicht mit Schlüsselwörtern (nicht, dass Ersteres eine gute Idee ist).
Gaefan
Es handelt sich nicht um eine Unterscheidung zwischen Funktion und Schlüsselwort, sondern um einen Funktionsaufruf gegen eine Anweisung . (Beispiel: print war früher eine Anweisung und arbeitete ohne Klammern).
Tomasz Gandor

Antworten:

128

Der letzte asserthätte Ihnen eine Warnung ( SyntaxWarning: assertion is always true, perhaps remove parentheses?) gegeben, wenn Sie ihn durch einen vollständigen Interpreter und nicht durch IDLE ausgeführt hätten. Da assertes sich um ein Schlüsselwort und nicht um eine Funktion handelt, übergeben Sie tatsächlich ein Tupel als erstes Argument und lassen das zweite Argument weg.

Denken Sie daran, dass nicht leere Tupel ausgewertet Truewerden. Da die Bestätigungsnachricht optional ist, haben Sie assert Truebeim Schreiben im Wesentlichen angerufen assert(1==2, "hi").

Mark Rushakoff
quelle
10
Der Grund dafür ist, dass assert (1==2)Klammern um einen einzelnen Ausdruck nicht automatisch ein Tupel erstellen. Sie würden das gleiche Verhalten wie # 4 erhalten, wenn Sie dies tun würden assert (1==2,). Das gleiche würde passieren, wenn Sie es print ('foo', 'bar')stattdessen tun würden print 'foo', 'bar'; Sie würden das ausgegebene Tupel sehen
Michael Mrozek
Es ist weiter hervorzuheben, dass Aussagen der Form assert(test, message)wahrscheinlich falsch und sicherlich verwirrend sind. Keine Eltern!
Tcarobruce
19
Also, was ist der richtige Weg, um eine lange Aussage zu PENT8 einzurücken? Scheint unmöglich.
Stantonk
30

Wenn Sie die Klammer dort einfügen, weil Sie eine mehrzeilige Zusicherung wünschen, können Sie alternativ einen Backslash am Ende der Zeile wie folgt einfügen:

foo = 7
assert foo == 8, \
    "derp should be 8, it is " + str(foo)

Drucke:

AssertionError: "derp should be 8, it is 7

Warum muss sich diese Python assertvon allem anderen unterscheiden:

Ich denke, die pythonische Ideologie ist, dass sich ein Programm selbst korrigieren sollte, ohne sich um die spezielle Flagge kümmern zu müssen, um Asserts einzuschalten. Die Versuchung, Behauptungen auszuschalten, ist zu groß und wird daher abgelehnt.

Ich teile Ihren Ärger darüber, dass Python assertim Vergleich zu allen anderen Python-Programmierkonstrukten eine eindeutige Syntax hat, und diese Syntax hat sich erneut von Python2 zu Python3 und erneut von Python 3.4 zu 3.6 geändert. Assert-Anweisungen von keiner Version zu einer anderen Version abwärtskompatibel machen.

Es ist ein Druck auf die Schulter, der assertein Bürger der 3. Klasse ist. Er wird in Python4 und sicherlich wieder in Python 8.1 vollständig entfernt.

Eric Leschinski
quelle
2
Gibt es ein Dokument darüber, was wir verwenden sollten, anstatt zu behaupten? Assert scheint ein solcher logischer Name für die Validierung zu sein und hat das gewünschte Verhalten, z. B. zeigt eine spezielle Meldung bei einem Fehler an.
AnneTheAgile
18

assert 1==2, "hi"wird wie assert 1==2, "hi"mit "hi" als zweitem Parameter für das Schlüsselwort analysiert . Daher gibt es richtig einen Fehler.

assert(1==2)wird als assert (1==2)identisch analysiert assert 1==2, da Parens um ein einzelnes Element kein Tupel erstellen, es sei denn, es gibt ein nachfolgendes Komma, z (1==2,).

assert(1==2, "hi")wird als analysiert assert (1==2, "hi"), was keinen Fehler ergibt, da ein nicht leeres Tupel (False, "hi")kein falscher Wert ist und dem Schlüsselwort kein zweiter Parameter zugewiesen wird.

Sie sollten keine Klammern verwenden, da dies assertin Python keine Funktion ist - es ist ein Schlüsselwort.

Bernstein
quelle
13

Sie können die Assert-Anweisung ohne Folgendes brechen \:

foo = 7
assert foo == 8, (
    'derp should be 8, it is ' + str(foo))

Oder wenn Sie noch längere Nachricht haben:

foo = 7
assert foo == 8, (
    'Lorem Ipsum is simply dummy text of the printing and typesetting '
    'industry. Lorem Ipsum has been the industry\'s standard dummy text '
    'ever since the 1500s'
)
Karantan
quelle
1
Interessante Idee. Ich hasse Backslashes für die Fortsetzung, und dies ist eine Alternative zum Umschließen von Assert in eine Utility-Funktion (die meine Lösung war).
Tomasz Gandor
1

Das Folgende wird aus dem Python-Dokument zitiert

Assert-Anweisungen sind eine bequeme Möglichkeit, Debugging-Assertions in ein Programm einzufügen:

assert_stmt ::= "assert" expression ["," expression]

Die einfache Form, Assert-Ausdruck, entspricht if __debug__: if not expression: raise AssertionError

Die erweiterte Form, assert expression1, expression2 , entspricht if __debug__: if not expression1: raise AssertionError(expression2)

Wenn Sie hier also Klammern verwenden, verwenden Sie die einfache Form, und der Ausdruck wird als Tupel ausgewertet. Dies ist immer wahr, wenn er in bool umgewandelt wird

VicX
quelle