Python assert zi bez nawiasów


104

Oto cztery proste wywołania assert:

>>> 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")

Zwróć uwagę, że ostatnia nie powoduje błędu. Jaka jest różnica między wywoływaniem funkcji assert z nawiasami lub bez, które powodują takie zachowanie? Moją praktyką jest używanie nawiasów, ale powyższe sugeruje, że nie powinienem.


Dzięki za pomocne odpowiedzi. Rozróżnienie między słowami kluczowymi a funkcjami wbudowanymi wydaje się subtelne. Oto lista słów kluczowych, dla których zakładam, że pareny powinny zostać pominięte: docs.python.org/reference/lexical_analysis.html#keywords
— gaefan

2
Jedną różnicą jest to, że możesz przedefiniować wbudowane funkcje, ale nie możesz tego zrobić za pomocą słów kluczowych (nie, że to pierwsze jest dobrym pomysłem).
— gaefan

Nie jest to rozróżnienie funkcji i słów kluczowych, ale wywołanie funkcji vs instrukcja . (na przykład - wydruk był kiedyś oświadczeniem i działał bez nawiasów).
— Tomasz Gandor

Odpowiedzi:


129

Ten ostatni assertdałby ci ostrzeżenie ( SyntaxWarning: assertion is always true, perhaps remove parentheses?), gdybyś przepuścił go przez pełny interpreter, a nie przez IDLE. Ponieważ assertjest to słowo kluczowe, a nie funkcja, w rzeczywistości przekazujesz krotkę jako pierwszy argument, a pozostawiasz drugi argument.

Przypomnij sobie, że niepuste krotki oceniają do True, a ponieważ komunikat potwierdzenia jest opcjonalny, w zasadzie zadzwoniłeś assert Truepodczas pisania assert(1==2, "hi").


10
Przyczyną nie assert (1==2)jest to, że nawiasy wokół pojedynczego wyrażenia nie utworzą automatycznie krotki; miałbyś takie samo zachowanie jak # 4, gdybyś to zrobił assert (1==2,). To samo by się stało, gdybyś zrobił print ('foo', 'bar')zamiast print 'foo', 'bar'; zobaczysz wypisaną krotkę
— Michael Mrozek

Warto dodatkowo podkreślić, że wypowiedzi w formularzu assert(test, message)prawdopodobnie są błędne, a na pewno mylące. Żadnych parens!
— tcarobruce

19
Jaki jest więc właściwy sposób wcięcia długiego stwierdzenia potwierdzającego, wrt PEP8? Wydaje się niemożliwe.
— stantonk


30

Jeśli umieścisz tam nawias, ponieważ chcesz uzyskać potwierdzenie wielowierszowe, alternatywą jest umieszczenie ukośnika odwrotnego na końcu linii w następujący sposób:

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

Wydruki:

AssertionError: "derp should be 8, it is 7

Dlaczego ten Python assertmusi się różnić od wszystkiego innego:

Myślę, że ideologia Pythona polega na tym, że program powinien samokorygować się bez martwienia się o specjalną flagę włączającą potwierdzenia. Pokusa wyłączania potwierdzeń jest zbyt duża i dlatego jest przestarzała.

Podzielam twoją irytację, że python assertma unikalną składnię w stosunku do wszystkich innych konstrukcji programowania w Pythonie, a ta składnia ponownie zmieniła się z python2 na python3 i ponownie z pythona 3.4 na 3.6. Sprawianie, że instrukcje assert nie są wstecznie kompatybilne z żadnej wersji do żadnej innej wersji.

To dotknięcie w ramię, które assertjest obywatelem trzeciej klasy, zostanie całkowicie usunięte w Pythonie4, a na pewno ponownie w Pythonie 8.1.


2
Czy istnieje dokument na temat tego, czego powinniśmy używać zamiast potwierdzać? Assert wydaje się taką logiczną nazwą do walidacji i ma pożądane zachowanie, np. Wyświetla specjalny komunikat w przypadku błędu.
— AnneTheAgile

18

assert 1==2, "hi"jest analizowany tak, jak assert 1==2, "hi"„hi” jako drugi parametr słowa kluczowego. Stąd, dlaczego poprawnie daje błąd.

assert(1==2)jest analizowany jako assert (1==2)identyczny z assert 1==2, ponieważ powiązania wokół pojedynczego elementu nie tworzą krotki, chyba że na końcu znajduje się przecinek, np (1==2,).

assert(1==2, "hi")jest analizowany jako assert (1==2, "hi"), co nie daje błędu, ponieważ niepusta krotka (False, "hi")nie jest wartością fałszywą i nie ma drugiego parametru dostarczonego do słowa kluczowego.

Nie powinieneś używać nawiasów, ponieważ assertnie jest to funkcja w Pythonie - to słowo kluczowe.


13

Możesz złamać oświadczenie assert bez \tego:

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

Lub jeśli masz jeszcze dłuższą wiadomość:

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'
)

1
Ciekawy pomysł. Nienawidzę odwrotnych ukośników jako kontynuacji i jest to alternatywa dla opakowywania assertów w funkcję narzędziową (co było moim rozwiązaniem).
— Tomasz Gandor

1

Poniższy cytat pochodzi z dokumentu Python

Instrukcje assert są wygodnym sposobem wstawiania asercji debugowania do programu:

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

Prosta forma, wyrażenie assert, jest równoważne if __debug__: if not expression: raise AssertionError

Forma rozszerzona, assert expression1, expression2 , jest równoważna if __debug__: if not expression1: raise AssertionError(expression2)

Więc kiedy używasz tutaj nawiasów, używasz prostej formy, a wyrażenie jest oceniane jako krotka, co jest zawsze Prawdą, gdy jest rzutowane na bool

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.