19 Stimmen

Null-Muster in Python zu wenig genutzt?

Hin und wieder stoße ich auf Code wie diesen:

foo = Foo()
...
if foo.bar is not None and foo.bar.baz == 42:
   shiny_happy(...)

Das erscheint mir, nun ja, unpythonisch.

In Objective-C können Sie Nachrichten an nil senden und als Antwort nil erhalten. Ich fand das schon immer ziemlich praktisch. Natürlich ist es möglich, eine Nullmuster in Python Nach den Ergebnissen zu urteilen, die mir Google liefert, scheint dies jedoch nicht sehr weit verbreitet zu sein. Warum ist das so?

Oder noch besser: Wäre es eine schlechte Idee, None.whatever None zurückgeben zu lassen, anstatt eine Ausnahme auszulösen?

20voto

mozillalives Punkte 1450

PEP 336 - Nicht abrufbar machen eine ähnliche Funktion vorgeschlagen:

None sollte ein aufrufbares Objekt sein, das beim Aufruf mit beliebigen Argumenten keine Nebenwirkung hat und None zurückgibt.

Die Begründung für die Ablehnung lautete schlicht und einfach: "Es handelt sich um eine Funktion, die beim Aufruf von None einen Fehler auslöst."

14voto

Eloff Punkte 19617

Es tut mir leid, aber dieser Code ist pythonisch. Ich denke, die meisten würden zustimmen, dass "explizit besser ist als implizit" in Python. Python ist eine Sprache, die im Vergleich zu den meisten anderen Sprachen leicht zu lesen ist, und man sollte das nicht durch kryptischen Code zunichte machen. Machen Sie die Bedeutung sehr klar.

foo = Foo()
...
if foo.bar is not None and foo.bar.baz == 42:
    shiny_happy(...)

In diesem Codebeispiel ist klar, dass foo.bar in diesem Codepfad manchmal None ist und dass wir shiny_happy() nur ausführen, wenn es nicht None ist und .baz == 42. Es ist für jeden klar, was hier vor sich geht und warum. Dasselbe kann nicht für das Null-Muster oder den try ... except-Code in einer der hier geposteten Antworten gesagt werden. Es ist eine Sache, wenn Ihre Sprache, wie Objective-C oder Javascript, ein Null-Muster erzwingt, aber in einer Sprache, in der es überhaupt nicht verwendet wird, führt es nur zu Verwirrung und schwer lesbarem Code. Wenn Sie in Python programmieren, tun Sie, was die Pythonistas tun.

13voto

Skilldrick Punkte 66961

Könnten Sie nicht einen Versuch machen, außer? Der pythonische Weg sagt Es ist einfacher, um Vergebung zu bitten als um Erlaubnis .

Also:

try:
    if foo.bar.baz == 42:
        shiny_happy(...)
except AttributeError:
    pass #or whatever

Oder es zu tun, ohne möglicherweise mehr Ausnahmen als gewünscht zum Schweigen zu bringen:

try:
    baz = foo.bar.baz
except AttributeError:
    pass # handle error as desired
else:
    if baz == 42:
        shiny_happy(...)

12voto

Jason Orendorff Punkte 39655

Die Handlichkeit geht auf Kosten von dummen Fehlern, die nicht zum frühestmöglichen Zeitpunkt entdeckt werden, und zwar so nah an der fehlerhaften Codezeile wie möglich.

Ich denke, dass diese spezielle Funktion bestenfalls gelegentlich nützlich ist, während dumme Fehler passieren. die ganze Zeit .


Ein SQL-ähnliches NULL wäre sicherlich schlecht für Tests, die sich darauf stützen, dass Aussagen entweder wahr oder falsch sind. Betrachten Sie diesen Code aus unittest.py:

class TestCase:
    ...
    def failUnless(self, expr, msg=None):
        """Fail the test unless the expression is true."""
        if not expr: raise self.failureException, msg

Nehmen wir nun an, ich habe einen Test, der dies tut:

conn = connect(addr)
self.failUnless(conn.isOpen())

Angenommen, connect gibt fälschlicherweise null zurück. Wenn ich das "Null-Muster" verwende, oder die Sprache es eingebaut hat, und conn null ist, dann conn.isOpen() Null ist, und not conn.isOpen() ist ebenfalls null, so dass die Behauptung geht , obwohl die Verbindung offensichtlich nicht offen ist.

Ich neige dazu zu denken NULL ist eine der schlechtesten Eigenschaften von SQL. Und die Tatsache, dass null In anderen Sprachen ist die stillschweigende Übergabe eines Objekts eines beliebigen Typs nicht viel besser. (Tony Hoare nannte Null-Referenzen "Mein Milliarden-Dollar-Fehler" .) Wir brauchen weniger von diesen Dingen, nicht mehr.

4voto

Steve Losh Punkte 19272

Wie bereits von anderen erwähnt, beschreibt PEP 336, warum dies der Fall ist.

Das Hinzufügen von etwas wie Groovy's " sicherer Schiffsführer " ( ?. ) könnten die Dinge in einigen Fällen vielleicht eleganter machen:

foo = Foo()

if foo.bar?.baz == 42:
    ...

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X