Do czego służy „aser” w Pythonie?


Odpowiedzi:


1082

assertOświadczenie istnieje w prawie każdym języku programowania. Pomaga wykryć problemy na wczesnym etapie programu, gdzie przyczyna jest wyraźna, a nie później jako efekt uboczny innej operacji.

Kiedy to zrobisz ...

assert condition

... każesz programowi przetestować ten warunek i natychmiast wywołać błąd, jeśli warunek jest fałszywy.

W Pythonie odpowiada to mniej więcej tak:

if not condition:
    raise AssertionError()

Wypróbuj w powłoce Pythona:

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

Asercje mogą zawierać opcjonalny komunikat i można je wyłączyć podczas uruchamiania interpretera.

Aby wydrukować wiadomość, jeśli asercja się nie powiedzie:

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

Czy nie używać nawiasów, aby wywołać assertjak funkcja. To jest oświadczenie. Jeśli to zrobisz assert(condition, message), uruchomisz assertz (condition, message)krotką jako pierwszym parametrem.

Jeśli chodzi o ich wyłączanie, podczas działania pythonw trybie zoptymalizowanym, gdzie __debug__jest False, instrukcje aser będą ignorowane. Wystarczy przekazać -Oflagę:

python -O script.py

Zobacz tutaj odpowiednią dokumentację.


92
Nit: assert jest instrukcją, a nie funkcją. I w przeciwieństwie do print , w Pythonie 3 jest to nadal stwierdzenie .
Bob Stein

2
@Chaine assert oznacza „upewnij się, że * coś” jest prawdą ”. A więc a == 3 upewni się, że a jest równe 3; jeśli a nie jest równe 3 (tj. A == 3 jest fałszem), to będzie zgłosić błąd
Ant

5
Jeśli mogę po prostu użyć if not condition: raise AssertError(), dlaczego powinienem użyć asercji? Czy są jakieś warunki, w których twierdzenie jest lepsze niż bycie krótszym if not conditionstwierdzeniem?
alpha_989

6
@ alpha_989 a) jest krótszy i bardziej czytelny, b) możesz wyłączyć instrukcje asercji podczas uruchamiania interpretera (nie w przypadku instrukcji if). Przeczytaj dokumentację, aby uzyskać więcej informacji :)
Slezica

9
zupełnie nie rozumiem, w jaki sposób ta odpowiedź zdobywa tak wiele głosów, w rzeczywistości inni też. pytanie brzmi „Jaki jest pożytek z„ asercji ”w Pythonie?”, więc pyta: kiedy używać, a ściślej: jaki jest scenariusz użycia assert, ale po przeczytaniu wszystkich odpowiedzi całkowicie nie mam nic, czego chcę!
lnshi

422

Uważaj na nawiasy. Jak już wspomniano powyżej, w Pythonie 3 assertnadal znajduje się stwierdzenie , więc analogicznie do print(..), można ekstrapolować to samo assert(..)lub raise(..)nie należy.

Jest to ważne, ponieważ:

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

nie zadziała, w przeciwieństwie do

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

Pierwszym powodem, dla którego pierwszy nie zadziała, jest bool( (False, "Houston we've got a problem") )ocena True.

W oświadczeniu assert(False)są to po prostu nadmiarowe nawiasy wokół False, które oceniają ich zawartość. Ale z assert(False,)nawiasami są teraz krotki, a niepuste krotki mają Truewartość logiczną.


18
Przybyłem tutaj, szukając dokładnych informacji na temat parens i następującego komunikatu. Dzięki.
superbeck

6
Ale assert (2 + 2 = 5), "Houston we've got a problem"powinno być ok, tak?
SherylHohman

4
@ SherylHohman możesz także spróbować uruchomić to sam i sprawdzić, czy to działa, czy nie
DarkCygnus

2
Nie zapominaj, że ludzie często używają nawiasów dla niejawnej kontynuacji linii zgodnej z PEP 8 Również nie zapominaj, że krotki nie są zdefiniowane w nawiasach, ale przez istnienie przecinka (krotki nie mają nic wspólnego z parens, z wyjątkiem celów pierwszeństwo operatora).
cowbert

4
assert (2 + 2 = 5), "Houston we've got a problem"nie będzie działać ... ale nie ma to nic wspólnego z instrukcją assert, co jest w porządku. Twój stan nie będzie działać, ponieważ nie jest to stan. Brakuje sekundy =.
n1k31t4,

133

Jak zauważyły ​​inne odpowiedzi, assertprzypomina rzucanie wyjątku, jeśli dany warunek nie jest spełniony. Ważną różnicą jest to, że instrukcje aser są ignorowane, jeśli skompilujesz kod z opcją optymalizacji -O. Dokumentacja mówi, że assert expressionmoże być lepiej opisane jako równoważne

if __debug__:
   if not expression: raise AssertionError

Może to być przydatne, jeśli chcesz dokładnie przetestować swój kod, a następnie wydać wersję zoptymalizowaną, gdy będziesz zadowolony, że żadna z twoich asercji nie zawiodła - gdy optymalizacja jest włączona, __debug__zmienna staje się False i warunki przestają być oceniane. Ta funkcja może Cię również złapać, jeśli polegasz na twierdzeniach i nie zdajesz sobie sprawy, że zniknęły.


Czy to oznacza, że ​​jeśli pewna zmienna lub poprawne dane wejściowe (zgodnie z umową, na podstawie której program jest napisany) mogą doprowadzić do awarii programu, gdy jest uruchamiany przez użytkownika (zakładając, że flaga -O jest używana, gdy użytkownik uruchamia program), powinieneś zamiast tego użyć if Not Error: raise Exception(“ this is a error”)? W ten sposób program nadal wyświetli źródło błędu, gdy użytkownik go uruchomi.
alpha_989

Z drugiej strony, jeśli spodziewasz się, że program może popełnić błąd z powodu nieprawidłowej logiki / implementacji kodu (ale nie z powodu danych wejściowych zgodnych z umową z użytkownikiem programu), powinieneś użyć assertinstrukcji? Zakłada się tutaj, że kiedy program zostanie wydany użytkownikowi końcowemu, używasz flagi -O, zakładając w ten sposób, że wszystkie błędy zostały usunięte. Dlatego też każdy błąd lub awaria programu wynika z danych wejściowych do programu, które są ważne zgodnie z umową, ale nie mogą być obsługiwane przez program. Powinien więc ostrzec użytkownika jako takiego.
alpha_989

@ alpha_989 to dokładnie prawda. Lubię myśleć o twierdzeniach jako o sprawdzeniach rozsądku, które mają jedynie pomóc jako programista upewnić się, że to, co uważasz za prawdę, jest prawdziwe podczas rozwoju.
Christopher Shroba

52

Celem asercji w Pythonie jest informowanie programistów o niemożliwych do naprawienia błędach w programie.

Asercje nie są przeznaczone do sygnalizowania oczekiwanych warunków błędu, takich jak „nie znaleziono pliku”, w których użytkownik może podjąć działania naprawcze (lub po prostu spróbować ponownie).

Innym sposobem na to jest stwierdzenie, że asercje są wewnętrznymi samokontrolami w twoim kodzie. Działają, deklarując niektóre warunki jako niemożliwe w twoim kodzie. Jeśli te warunki się nie utrzymają, oznacza to błąd w programie.

Jeśli twój program nie zawiera błędów, te warunki nigdy nie wystąpią. Ale jeśli wystąpi jeden z nich , program ulegnie awarii z błędem asercji, informującym dokładnie, który warunek „niemożliwy” został wywołany. Dzięki temu znacznie łatwiej jest wyśledzić i naprawić błędy w swoich programach.

Oto podsumowanie z samouczka na temat twierdzeń Pythona, które napisałem:

Instrukcja assert Pythona stanowi pomoc w debugowaniu, a nie mechanizm obsługi błędów w czasie wykonywania. Celem stosowania asercji jest umożliwienie programistom szybszego znalezienia prawdopodobnej przyczyny błędu. Błąd asercji nigdy nie powinien być zgłaszany, chyba że w twoim programie jest błąd.


Dzięki za artykuł. Bardzo pomocne, aby zrozumieć assertoświadczenie i kiedy go używać. Próbuję zrozumieć kilka terminów wprowadzonych w tym artykule.
alpha_989

Pomyślałem, że zamieściłem tutaj komentarze, aby o wiele więcej osób mogło skorzystać z wyjaśnień. Przepraszam, jeśli pytania są zbyt naiwne.
alpha_989

Na blogu, który podlinkowałeś, podajesz przykład, w którym wspomniałeś, że `assert 0 <= price <= product ['price']` jest poprawny, ale używając `assert user.is_admin (), 'Musi mieć uprawnienia administratora, aby usunąć '' i assert store.product_exists(product_id), 'Unknown product id'nie jest dobrą praktyką, ponieważ jeśli debugowanie zostanie wyłączone, to usernawet jeśli nie adminbędzie w stanie usunąć produktu. Czy uważają Państwo, assert user.is_admin()jako unrecoverablebłąd? Dlaczego to nie jest self-check?
alpha_989

Jeśli uważasz, że 'user.is_admin () `jest danymi wejściowymi użytkownika, a zatem nie należy ich używać w assert statement, czy nie pricemożna również uznać za dane wejściowe użytkownika? Dlaczego uważasz za assert user.is_admin()walidację danych, ale nie assert price?
alpha_989

1
@LaryxDecidua Nie, możesz po prostu przeczytać to na mojej stronie, samouczek jest publicznie dostępny. Wystarczy nacisnąć Escape lub kliknąć mały symbol „x”, jeśli nie jesteś zainteresowany biuletynem. Mam nadzieję, że to pomoże :-)
dbader

51

Inni już dali ci linki do dokumentacji.

Możesz wypróbować następujące opcje w interaktywnej powłoce:

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

Pierwsze zdanie nic nie robi, a drugie podnosi wyjątek. Jest to pierwsza wskazówka: aserty są przydatne do sprawdzania warunków, które powinny być prawdziwe w danej pozycji kodu (zwykle na początku (warunki wstępne) i na końcu funkcji (warunki dodatkowe)).

Aserty są w rzeczywistości ściśle powiązane z programowaniem na podstawie umowy, co jest bardzo przydatną praktyką inżynierską:

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


Czy to oznacza, że ​​możemy wpisać kod w sytuacji takiej jak assert (2> 5) i zgłosić błąd, aby kontynuować?

20
Strać parens, assert nie jest funkcją.
pillmuncher

2
Utrata parens jest ważniejsza niż się wydaje. Patrz poniżej .
Evgeni Sergeevev,

6
Assert faktycznie sięga (na długo przed „kontraktami”) do Turinga, kiedy napisał jeden z pierwszych artykułów na temat tego, jak programiści mogą poradzić sobie z dość trudnym zadaniem tworzenia poprawnych programów. Znalezienie tego papieru jest zadaniem czytelnika, ponieważ wszyscy programiści mogą skorzystać z zapoznania się z jego pracą. :-) turingarchive.org
Ron Burk

17

Z dokumentów:

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

Tutaj możesz przeczytać więcej: http://docs.python.org/release/2.5.2/ref/assert.html


podoba mi się ten komentarz, ponieważ wyjaśnia on, co jest bardzo prosty. moje pytanie brzmi: „jeśli napisałem odpowiedni test jednostkowy, dlaczego miałbym potrzebować asercji”? te rzeczy i tak nie działają w produkcji.
dtc

17

Instrukcja assert ma dwie formy.

Prosta forma assert <expression>, jest odpowiednikiem

if __debug__:
    if not <expression>: raise AssertionError

Rozszerzona forma assert <expression1>, <expression2>, jest równoważna

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

16

Asercje to systematyczny sposób sprawdzania, czy wewnętrzny stan programu jest zgodny z oczekiwaniami programisty, w celu wykrycia błędów. Zobacz przykład poniżej.

>>> 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
Asercje można również często stosować w programach testów jednostkowych. stackoverflow.com/questions/1383/what-is-unit-testing
panofish

7

Oto prosty przykład, zapisz to w pliku (powiedzmy b.py)

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


chkassert('a')

a wynik kiedy $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

jeśli instrukcja po potwierdzeniu jest prawdziwa, program kontynuuje działanie, ale jeśli instrukcja po potwierdzeniu jest fałszywa, wówczas program podaje błąd. Proste.

na przykład:

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

assertOświadczenie istnieje w prawie każdym języku programowania. Pomaga wykryć problemy na wczesnym etapie programu, gdzie przyczyna jest wyraźna, a nie później jako efekt uboczny innej operacji. Zawsze oczekują Truewarunku.

Kiedy robisz coś takiego:

assert condition

Mówisz programowi, aby przetestował ten warunek i natychmiast wywołał błąd, jeśli jest fałszywy.

W Pythonie assertwyrażenie jest równoważne z:

if __debug__:
    if not <expression>: raise AssertionError

Możesz użyć wyrażenia rozszerzonego, aby przekazać opcjonalny komunikat :

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

Wypróbuj w interpreterie języka Python:

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

Jest kilka ostrzeżeń, które należy zobaczyć przed użyciem ich głównie dla tych, którzy uważają, że przełączają się między instrukcjami asserti if. Celem jest użycie, assertgdy program weryfikuje warunek i zwraca wartość, która powinna natychmiast zatrzymać program, zamiast wybierać alternatywny sposób obejścia błędu:

1. Nawiasy

Jak zapewne zauważyłeś, assertinstrukcja wykorzystuje dwa warunki. Dlatego nie używaj nawiasów, aby je globalizować jako oczywiste porady. Jeśli to zrobisz:

assert (condition, message)

Przykład:

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

Będziesz działał assertz (condition, message)parametrem, który reprezentuje krotkę jako pierwszy parametr, a dzieje się tak, ponieważ niepuste krotki w Pythonie są zawszeTrue . Możesz jednak zrobić to oddzielnie bez problemu:

assert (condition), "message"

Przykład:

>>> 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. Cel debugowania

Jeśli zastanawiasz się, kiedy użyć assertinstrukcji. Weź przykład wykorzystany w prawdziwym życiu:

* Gdy twój program ma tendencję do kontrolowania każdego parametru wprowadzonego przez użytkownika lub cokolwiek innego:

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

* Kolejny przypadek dotyczy matematyki, gdy 0 lub wartość dodatnia jako współczynnik lub stała na pewnym równaniu:

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

* lub nawet prosty przykład implementacji boolean:

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

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

3. Przetwarzanie lub walidacja danych

Niezwykle ważne jest, aby nie polegać na assertinstrukcji do przetwarzania danych lub sprawdzania poprawności danych, ponieważ tę instrukcję można wyłączyć przy inicjalizacji języka Python za pomocą -Olub -OOflagi - odpowiednio wartości 1, 2 i 0 (domyślnie) - lub PYTHONOPTIMIZEzmiennej środowiskowej .

Wartość 1:

* twierdzenia są wyłączone;

* pliki kodu bajtowego są generowane przy użyciu .pyorozszerzenia zamiast .pyc;

* sys.flags.optimizejest ustawiony na 1 ( True);

* i __debug__jest ustawiony na False;

Wartość 2: wyłącza jeszcze jedną rzecz

* dokumenty są wyłączone;

Dlatego używanie assertinstrukcji do sprawdzania poprawności rodzaju oczekiwanych danych jest niezwykle niebezpieczne, co sugeruje nawet pewne problemy z bezpieczeństwem. Następnie, jeśli potrzebujesz zweryfikować jakieś pozwolenie, polecam raise AuthErrorzamiast tego. Jako warunek wstępny, programista assertjest powszechnie używany przez programistów w bibliotekach lub modułach, które nie wymagają bezpośredniej interakcji użytkownika.


3

Jak streszczono zwięźle na Wiki Wiki :

Asercja jest wyrażeniem logicznym w określonym punkcie programu, co będzie prawdziwe, chyba że w programie wystąpi błąd.

Za pomocą assertinstrukcji można udokumentować zrozumienie kodu w określonym punkcie programu. Na przykład można udokumentować założenia lub gwarancje dotyczące danych wejściowych (warunki wstępne), stanu programu (niezmienniki) lub wyników (warunki dodatkowe).

Jeśli twoje twierdzenie kiedykolwiek się nie powiedzie, jest to ostrzeżenie dla ciebie (lub twojego następcy), że twoje zrozumienie programu było błędne, kiedy go napisałeś, i że prawdopodobnie zawiera błąd.

Aby uzyskać więcej informacji, John Regehr ma wspaniały wpis na blogu na temat korzystania z asercji , który dotyczy również assertinstrukcji Python .


2

Jeśli kiedykolwiek chcesz dokładnie wiedzieć, co funkcja zarezerwowana robi w Pythonie, wpisz help(enter_keyword)

Upewnij się, że jeśli wprowadzasz zarezerwowane słowo kluczowe, które wpisujesz jako ciąg.


2

Aser Python jest w zasadzie pomocą do debugowania, która testuje warunki wewnętrznej kontroli twojego kodu. Assert sprawia, że ​​debugowanie jest naprawdę łatwe, gdy kod wpada w niemożliwe przypadki brzegowe. Zapewnij sprawdź te niemożliwe przypadki.

Załóżmy, że istnieje funkcja obliczania ceny produktu po rabacie:

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

w tym przypadku cena ze zniżką nigdy nie może być mniejsza niż 0 i większa od rzeczywistej ceny. Tak więc, w przypadku naruszenia powyższego warunku, assert wywołuje błąd asercji, który pomaga deweloperowi zidentyfikować, że stało się coś niemożliwego.

Mam nadzieję, że to pomoże :)


2
assertjest przydatny w kontekście debugowania, ale nie należy na nim polegać poza kontekstem debugowania.
FluxIX

2

Moje krótkie wyjaśnienie to:

  • assertpodnosi, AssertionErrorjeśli wyrażenie jest fałszywe, w przeciwnym razie po prostu kontynuuje kod, a jeśli jest przecinek, czymkolwiek będzie AssertionError: whatever after comma, a kod jest jak:raise AssertionError(whatever after comma)

Powiązany samouczek na ten temat:

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


Odpowiedź zawiera informacje o tym, jak używać assert, ale nie kiedy używać (lub nie używać) assert; również zauważyć, że assertmoże być wyłączona, jeśli __debug__znaczy Falsebyłaby przydatna.
FluxIX

1

W programie Pycharm, jeśli użyjesz assertgo isinstancedo zadeklarowania typu obiektu, pozwoli ci on uzyskać dostęp do metod i atrybutów obiektu nadrzędnego podczas kodowania, automatycznie się uzupełni.

Załóżmy na przykład, że self.object1.object2jest MyClassobiektem.

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

Jak napisano w innych odpowiedziach, assertinstrukcje służą do sprawdzania stanu programu w danym punkcie.

Nie powtórzę tego, co zostało powiedziane na temat powiązanej wiadomości, nawiasów lub -Oopcji i __debug__stałej. Sprawdź także dokument, aby uzyskać informacje z pierwszej ręki. Skoncentruję się na twoim pytaniu: do czego służy assert? Mówiąc dokładniej, kiedy (a kiedy nie) należy użyć assert?

Te assertstwierdzenia są przydatne do debugowania programu, ale zniechęcony do sprawdzenia danych wprowadzonych przez użytkownika. Używam następującej zasady: zachowaj twierdzenia, aby wykryć, że taka sytuacja nie powinna się zdarzyć . Wprowadzane przez użytkownika dane mogą być niepoprawne, np. Hasło jest za krótkie, ale nie jest to przypadek, który nie powinien się zdarzyć . Jeśli średnica koła nie jest dwa razy większa niż jego promień, oznacza to, że nie powinno się to zdarzyć .

Moim zdaniem najciekawsze użycie assertinspirowane jest programowaniem na podstawie umowy, jak opisano przez B. Meyera w [Object-Oriented Software Construction] ( https://www.eiffel.org/doc/eiffel/Object-Oriented_Software_Construction% 2C_2nd_Edition ) i zaimplementowane w [języku programowania Eiffel] ( https://en.wikipedia.org/wiki/Eiffel_(programming_language) ). Nie można w pełni emulować programowania na podstawie umowy za pomocą assertinstrukcji, ale warto zachować intencję.

Oto przykład. Wyobraź sobie, że musisz napisać headfunkcję (jak [ headfunkcja w Haskell] ( http://www.zvon.org/other/haskell/Outputprelude/head_f.html )). Podana specyfikacja to: „jeśli lista nie jest pusta, zwróć pierwszą pozycję na liście”. Spójrz na następujące implementacje:

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

I

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

(Tak, można to zapisać jako return xs[0] if xs else None, ale nie o to chodzi) .

Jeśli lista nie jest pusta, obie funkcje mają ten sam wynik i ten wynik jest poprawny:

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

Dlatego obie implementacje są (mam nadzieję) poprawne. Różnią się, gdy próbujesz zabrać nagłówek pustej listy:

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

Ale:

>>> head2([]) is None
True

Ponownie obie implementacje są poprawne, ponieważ nikt nie powinien przekazywać pustej listy do tych funkcji (jesteśmy poza specyfikacją ). To niepoprawne połączenie, ale jeśli wykonasz takie połączenie, wszystko może się zdarzyć. Jedna funkcja wywołuje wyjątek, druga zwraca specjalną wartość. Najważniejsze jest: nie możemy polegać na tym zachowaniu . Jeśli xsjest pusty, to zadziała:

print(head2(xs))

Spowoduje to jednak awarię programu:

print(head1(xs))

Aby uniknąć niespodzianek, chciałbym wiedzieć, kiedy przekazuję nieoczekiwany argument funkcji. Innymi słowy: chciałbym wiedzieć, kiedy obserwowalne zachowanie nie jest wiarygodne, ponieważ zależy to od implementacji, a nie od specyfikacji. Oczywiście mogę przeczytać specyfikację, ale programiści nie zawsze dokładnie czytają dokumenty.

Wyobraź sobie, że mam sposób, aby wstawić specyfikację do kodu, aby uzyskać następujący efekt: gdy naruszę specyfikację, np. Przekazując pustą listę head, otrzymam ostrzeżenie. Byłoby to bardzo pomocne w napisaniu poprawnego (tj. Zgodnego ze specyfikacją) programu. I tam assert wkracza na scenę:

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

I

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

Teraz mamy:

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

I:

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

Zauważ, że head1wyrzuca an AssertionError, a nie an IndexError. Jest to ważne, ponieważ an AssertionErrornie jest żadnym błędem środowiska wykonawczego: sygnalizuje naruszenie specyfikacji. Chciałem ostrzeżenia, ale pojawia się błąd. Na szczęście mogę wyłączyć kontrolę (korzystając z -Oopcji), ale na własne ryzyko. Zrobię to, awaria jest naprawdę droga i mam nadzieję na najlepsze. Wyobraź sobie, że mój program jest osadzony w statku kosmicznym, który podróżuje przez czarną dziurę. Wyłączę asercje i mam nadzieję, że program jest wystarczająco solidny, aby nie powodować awarii tak długo, jak to możliwe.

Ten przykład dotyczył tylko warunków wstępnych, assertponieważ można użyć do sprawdzenia warunków dodatkowych (wartość zwracana i / lub stan) i niezmienników (stan klasy). Pamiętaj, że sprawdzanie warunków dodatkowych i niezmienników za pomocą assertmoże być kłopotliwe:

  • w przypadku warunków dodatkowych należy przypisać wartość zwracaną do zmiennej, a może przechowywać stan początkowy obiektu, jeśli ma się do czynienia z metodą;
  • w przypadku niezmienników należy sprawdzić stan przed i po wywołaniu metody.

Nie będziesz mieć czegoś tak wyrafinowanego jak Eiffel, ale możesz jednak poprawić ogólną jakość programu.


Podsumowując, assertstwierdzenie to wygodny sposób na wykrycie takiej sytuacji, która nie powinna się zdarzyć . Naruszenie specyfikacji (np. Przekazanie pustej listy head) jest pierwszą klasą, nie powinno się zdarzyć . Dlatego chociaż assertoświadczenie może być użyte do wykrycia każdej nieoczekiwanej sytuacji, jest to uprzywilejowany sposób zapewnienia spełnienia specyfikacji. Po wstawieniu assertinstrukcji do kodu reprezentujących specyfikację możemy mieć nadzieję, że poprawiłeś jakość programu, ponieważ zostaną zgłoszone niepoprawne argumenty, niepoprawne wartości zwracane, niepoprawne stany klasy ...


-2

format: assert Expression [, argumenty] Gdy aser napotka instrukcję, Python ocenia wyrażenie. Jeśli instrukcja nie jest prawdziwa, zgłaszany jest wyjątek (assertionError). Jeśli asercja się nie powiedzie, Python użyje ArgumentExpression jako argumentu dla AssertionError. Wyjątki AssertionError mogą być wychwytywane i obsługiwane jak każdy inny wyjątek za pomocą instrukcji try-wyjątek, ale jeśli nie zostaną obsłużone, zakończą program i wygenerują śledzenie. Przykład:

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)    

Wykonanie powyższego kodu powoduje następujący wynik:

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

Może być użyty, aby zapewnić przekazanie parametrów w wywołaniu funkcji.


1
To zadziała, ale z tego, co rozumiem, twierdzeń nie należy używać do sprawdzania danych wejściowych użytkownika, ponieważ można je wyłączyć w czasie wykonywania. Jeśli naprawdę chcesz wymusić lub zweryfikować dane wprowadzone przez użytkownika, if not user_key: raise ValueError()sprawdź tutaj ostatnie 2 akapity: wiki.python.org/moin/UsingAssertionsEffectively
alpha_989

assertnie powinien być używany do sprawdzania poprawności danych wejściowych, ponieważ sprawdzanie poprawności zostanie usunięte, jeśli tak __debug__jest False. Również stosowanie asercji do celów innych niż debugowanie może spowodować, że ludzie złapią wynikowe AssertionErrors, co może utrudnić debugowanie zamiast go zmniejszyć.
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

Zasadniczo znaczenie słowa kluczowego assert polega na tym, że jeśli warunek nie jest spełniony, to przez asertywność lub w przeciwnym razie kontynuuje na przykład w pythonie.

kod-1

a=5

b=6

assert a==b

WYNIK:

assert a==b

AssertionError

kod-2

a=5

b=5

assert a==b

WYNIK:

Process finished with exit code 0

2
proszę poprawnie sformatować kod. jak to się poprawia w stosunku do poprzednich odpowiedzi?
c2huc2hu

czy jest jakiś problem w moim wyjaśnieniu?
ujjwal_bansal

twoje wyjaśnienie nie dodaje niczego do istniejących odpowiedzi, a słaba gramatyka utrudnia czytanie. jeśli szukasz pytań, na które chcesz odpowiedzieć, rozważ przejrzenie nowego kanału pytań.
c2huc2hu

Podana odpowiedź nie zawiera odpowiedzi na pytanie, jak użyć assert, ale nie odpowiada, kiedy należy użyć (lub nie) assert.
FluxIX
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.