Frage

  1. Gibt es eine Performance oder Codewartungsproblem assert als Teil des Standard-Code anstelle der Verwendung es nur für Debugging-Zwecke bei der Verwendung?

    Ist

    assert x >= 0, 'x is less than zero'
    

    besser oder schlechter als

    if x < 0:
        raise Exception, 'x is less than zero'
    
  2. Außerdem ist es eine Möglichkeit, eine Geschäftsregel wie if x < 0 raise error zu setzen, die immer ohne try/except/finally so aktiviert, wenn jederzeit über den gesamten Code x ist kleiner als 0 ist ein Fehler ausgelöst, wie wenn Sie assert x < 0 eingestellt auf der Beginn einer Funktion an jedem Ort innerhalb der Funktion, wo x wird weniger als 0 eine Exception ausgelöst wird?

War es hilfreich?

Lösung

Um in der Lage sein, automatisch einen Fehler zu werfen, wenn x ich weniger als Null in der gesamten Funktion. Sie können Klasse Deskriptoren verwenden. Hier ein Beispiel:

class LessThanZeroException(Exception):
    pass

class variable(object):
    def __init__(self, value=0):
        self.__x = value

    def __set__(self, obj, value):
        if value < 0:
            raise LessThanZeroException('x is less than zero')

        self.__x  = value

    def __get__(self, obj, objType):
        return self.__x

class MyClass(object):
    x = variable()

>>> m = MyClass()
>>> m.x = 10
>>> m.x -= 20
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "my.py", line 7, in __set__
    raise LessThanZeroException('x is less than zero')
LessThanZeroException: x is less than zero

Andere Tipps

ASSERTS sollte verwendet werden, Bedingungen zu testen, dass sollte nie passieren . Der Zweck ist, früh im Fall eines korrupten Programmzustandes zum Absturz bringen.

Ausnahmen sollten für Fehler verwendet werden, die möglicherweise passieren kann, und Sie sollten fast immer Ihre eigenen Exception-Klassen erstellen .


Zum Beispiel, wenn Sie eine Funktion gerade schreiben aus einer Konfigurationsdatei in eine dict, falsche Formatierung in der Datei zu lesen, sollte einen ConfigurationSyntaxError erhöhen, während Sie assert können, dass Sie nicht dabei sind None zurückzukehren.


In Ihrem Beispiel wenn x ein Wert über eine Benutzeroberfläche oder von einer externen Quelle eingestellt ist, wird eine Ausnahme ist am besten.

Wenn x nur von Ihrem eigenen Code in dem gleichen Programm, gehen Sie mit der Behauptung festgelegt ist.

"behaupten" Aussagen entfernt werden, wenn die Kompilierung optimiert . Also, ja, gibt es sowohl Leistung und funktionelle Unterschiede.

  

Der aktuelle Code-Generator sendet keinen Code für eine assert-Anweisung, wenn Optimierung bei der Kompilierung angefordert wird. - Python 2.6.4 Docs

Wenn Sie assert verwenden Anwendungsfunktionalität zu implementieren, dann der Einsatz zur Optimierung der Produktion, werden Sie geplagt von „But-it-Werke-in-dev“ Defekte.

Siehe PYTHONOPTIMIZE und - O -OO

Die vier Zwecke assert

Angenommen, Sie auf 200.000 Zeilen Code arbeitet mit vier Kollegen Alice, Bernd, Carl, und Daphne. Sie nennen Ihren Code, Sie ihren Code nennen.

Dann assert hat vier Rollen :

  1. Inform Alice, Bernd, Carl, und Daphne, was Ihr Code erwartet.
    Angenommen, Sie haben eine Methode, die eine Liste von Tupeln und die Programmlogik verarbeitet brechen kann, wenn diese Tupel nicht unveränderlich sind:

    def mymethod(listOfTuples):
        assert(all(type(tp)==tuple for tp in listOfTuples))
    

    Dies ist vertrauenswürdiger als gleichwertige Informationen in der Dokumentation und viel leichter zu pflegen.

  2. Informieren Sie den Computer, was Ihr Code erwartet.
    assert erzwingt das richtige Verhalten von den Anrufern Ihres Codes. Wenn Ihr Code ruft Alices des und Bernds Code ruft bei Ihnen, dann ohne assert, wenn das Programm abstürzt in Alices Code, Bernd könnte annehmen, dass es Alice 'Schuld war, Alice untersucht und könnte annehmen, es war deine Schuld, Sie untersuchen und Bernd sagen, dass es in der Tat war sein. Viel Arbeit verloren.
    Mit behauptet, wer einen Anruf falsch bekommt, werden sie schnell in der Lage sein, es war zu sehen, ihre Schuld, nicht verkaufen. Alice, Bernd, und Sie alle profitieren. Speichert immense Mengen an Zeit.

  3. Informieren Sie die Leser Ihres Codes (einschließlich sich selbst), was Ihr Code an einem bestimmten Punkt erreicht hat.
    Angenommen, Sie haben eine Liste von Einträgen und jeder von ihnen kann sauber sein (was gut ist) oder es kann sein smorsh, TRALE, gullup oder twinkled (die alle nicht akzeptabel sind). Wenn es smorsh es unsmorshed sein muss; wenn es Trale es baludoed werden muss; wenn es gullup muss (und dann möglicherweise Tempo, auch) trottete werden; wenn es blitzt muss es wieder außer donnerstags blitzten werden. Sie erhalten die Idee: Es kompliziertes Zeug. Aber das Endergebnis ist (oder sein sollte), dass alle Einträge sauber sind. The Right Thing (TM) zu tun, ist die Wirkung Ihrer zusammenzufassen Reinigungsschleife als

    assert(all(entry.isClean() for entry in mylist))
    

    Diese Aussagen speichert Kopfschmerzen für alle versuchen zu verstehen, was genau es ist, dass die wunderbare Schleife zu erreichen. Und die häufigste dieser Menschen werden sich wahrscheinlich.

  4. Informieren Sie den Computer, was Ihr Code an einem bestimmten Punkt erreicht hat.
    Sollten Sie jemals vergessen einen Eintrag schreiten sie nach trotten benötigen, die assert Ihren Tag speichern und vermeiden, dass Ihr Code Pausen lieber Daphnes viel später.

In meinem Kopf assert die beiden Zwecke der Dokumentation (1 und 3) und Sicherung (2 und 4) sind gleich wertvoll.
kann die Menschen zu informieren, auch sein mehr wert als den Computer zu informieren weil es die sehr Fehler verhindern kann, zielt darauf ab, die assert (im Fall 1) zu fangen und viele nachfolgende Fehler in jedem Fall.

Zusätzlich zu den anderen Antworten, behauptet sich Ausnahmen auslösen, sondern nur AssertionErrors. Von einem utilitaristischen Standpunkt, sind Aussagen für nicht geeignet, wenn Sie feinkörnig Kontrolle über benötigen, welche Ausnahmen Sie fangen.

Das einzige, was bei diesem Ansatz wirklich falsch ist, dass es schwer ist, eine sehr beschreibend Ausnahme mit assert Aussagen zu machen. Wenn Sie sich für die einfachere Syntax suchen, erinnern Sie können auch so etwas tun:

class XLessThanZeroException(Exception):
    pass

def CheckX(x):
    if x < 0:
        raise XLessThanZeroException()

def foo(x):
    CheckX(x)
    #do stuff here

Ein weiteres Problem besteht darin, dass für die normale Zustand Prüfung behaupten ist, dass es es schwierig macht, das Debugging behauptet mit dem -O-Flag zu deaktivieren.

Wie bereits gesagt wurde, Behauptungen verwendet werden sollten, wenn Sie Ihren Code, sollten Sie nicht immer einen Punkt erreichen, was bedeutet, es ist ein Fehler vorhanden ist. Wahrscheinlich der nützlichste Grund sehe ich eine Aussage zu verwenden, ist eine Invariante / pre / Nachbedingung. Diese sind etwas, das am Anfang oder Ende jeder Iteration einer Schleife oder eine Funktion wahr sein muss.

Zum Beispiel kann eine rekursive Funktion (2 getrennte Funktionen so behandelt 1 schlecht Eingang und die anderen Griffe schlechten Code, weil es schwer ist, mit Rekursion zu unterscheiden). Dies würde es offensichtlich machen, wenn ich die if-Anweisung zu schreiben vergessen, was falsch gelaufen war.

def SumToN(n):
    if n <= 0:
        raise ValueError, "N must be greater than or equal to 0"
    else:
        return RecursiveSum(n)

def RecursiveSum(n):
    #precondition: n >= 0
    assert(n >= 0)
    if n == 0:
        return 0
    return RecursiveSum(n - 1) + n
    #postcondition: returned sum of 1 to n

Diese oft Schleifeninvarianten können mit einer Behauptung dargestellt werden.

Die englische Sprache Wort Assertion ist hier im Sinne von schwören , affirm , avow . Es bedeutet nicht, "check" oder "sollte" . Es bedeutet, dass Sie als Coder ein vereidigten Aussage machen sich hier:

# I solemnly swear that here I will tell the truth, the whole truth, 
# and nothing but the truth, under pains and penalties of perjury, so help me FSM
assert answer == 42

Wenn der Code korrekt ist, abgesehen von Einzel-event aufregt , Hardware-Ausfällen und solche, < strong> scheitern kein assert jemals . Deshalb ist das Verhalten des Programms an einen Endverbraucher nicht beeinträchtigt werden darf. Insbesondere versagt eine Assertion kann nicht einmal unter außergewöhnlichen programmatischen Bedingungen . Es funktioniert einfach nicht immer passieren. Wenn es geschieht, sollte der Programmierer dafür gezappt werden.

Is ein Performance-Problem?

  • Bitte denken Sie daran, "es zuerst funktioniert, bevor Sie es schnell funktioniert" .
    Nur sehr wenige Prozent aller Programme sind in der Regel relevant für seine Geschwindigkeit. Sie können jederzeit rauszuschmeißen oder eine assert vereinfachen, wenn es jemals beweist ein Performance-Problem sein -. und die meisten von ihnen wird es nie

  • Seien Sie pragmatisch :
    Angenommen, Sie haben eine Methode, die eine nicht-leere Liste von Tupeln und die Programmlogik verarbeitet wird brechen, wenn diese Tupel nicht unveränderlich ist. Sie sollten schreiben:

    def mymethod(listOfTuples):
        assert(all(type(tp)==tuple for tp in listOfTuples))
    

    Dies ist wahrscheinlich gut, wenn Ihre Listen sind in der Regel zehn Einträge lang sein, aber es kann ein Problem werden, wenn sie eine Million Einträge. Aber anstatt zu verwerfen diesem wertvollen Scheck vollständig könnten Sie einfach degradieren es zu

    def mymethod(listOfTuples):
        assert(type(listOfTuples[0])==tuple)  # in fact _all_ must be tuples!
    

    , die billig ist, aber wahrscheinlich fangen die meisten der eigentlichen Programmfehler trotzdem.

Es gibt einen Rahmen JBoss für java Drools , die Laufzeitüberwachung tut, um Geschäftsregeln durchsetzen, die die Antworten zweiter Teil Ihrer Frage. Ich bin aber nicht sicher, ob es einen solchen Rahmen für Python ist.

Ein Assert ist zu überprüfen -
1. die gültige Bedingung,
2. die gültige Aussage,
3. wahre Logik;
des Quellcodes. Anstatt das gesamte Projekt andernfalls gibt es einen Alarm aus, dass etwas in der Quelldatei nicht geeignet ist.

In Beispiel 1, da Variable 'str' ist nicht nul. Also keine jede Assertion oder Exception-Behandlung erhalten.

Beispiel 1:

#!/usr/bin/python

str = 'hello Pyhton!'
strNull = 'string is Null'

if __debug__:
    if not str: raise AssertionError(strNull)
print str

if __debug__:
    print 'FileName '.ljust(30,'.'),(__name__)
    print 'FilePath '.ljust(30,'.'),(__file__)


------------------------------------------------------

Output:
hello Pyhton!
FileName ..................... hello
FilePath ..................... C:/Python\hello.py

Im Beispiel 2 var 'str' ist nul. So sparen wir den Benutzer vor geht vor fehlerhaftem Programm von Assertion Erklärung.

Beispiel 2:

#!/usr/bin/python

str = ''
strNull = 'NULL String'

if __debug__:
    if not str: raise AssertionError(strNull)
print str

if __debug__:
    print 'FileName '.ljust(30,'.'),(__name__)
    print 'FilePath '.ljust(30,'.'),(__file__)


------------------------------------------------------

Output:
AssertionError: NULL String

Der Moment, wir wollen nicht, debuggen und erkennen die Behauptung Problem im Quellcode. Deaktivieren Sie die Optimierung Flag

python -O assertStatement.py
nichts wird Druck bekommen

In IDE wie PTVs, PyCharm, Flügel assert isinstance() Anweisungen verwendet werden können Code-Vervollständigung für einige unklare Objekte zu ermöglichen.

Wenn Sie mit Legacy-Code zu tun hat, die auf assert verlässt sich richtig zu funktionieren, obwohl sollte es nicht , dann den folgenden Code hinzuzufügen, ist eine schnelle Lösung, bis Sie Zeit finden, Refactoring:

try:
    assert False
    raise Exception('Python Assertions are not working. This tool relies on Python Assertions to do its job. Possible causes are running with the "-O" flag or running a precompiled (".pyo" or ".pyc") module.')
except AssertionError:
    pass
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top