520 Stimmen

Gibt es eine Python-Entsprechung des C# Null-Koaleszenz-Operators?

In C# gibt es eine Nullkoalitionsoperator (geschrieben als ?? ), die eine einfache (kurze) Nullprüfung während der Zuweisung ermöglicht:

string s = null;
var other = s ?? "some default value";

Gibt es eine Entsprechung in Python?

Ich weiß, dass ich es kann:

s = None
other = s if s else "some default value"

Aber gibt es einen noch kürzeren Weg (bei dem ich nicht wiederholen muss s )?

685voto

Juliano Punkte 35709
other = s or "some default value"

Ok, es muss geklärt werden, wie die or Betreiber arbeitet. Er ist ein boolescher Operator, funktioniert also in einem booleschen Kontext. Wenn die Werte nicht boolesch sind, werden sie für die Zwecke des Operators in boolesch umgewandelt.

Beachten Sie, dass die or Operator gibt nicht nur True o False . Stattdessen wird der erste Operand zurückgegeben, wenn der erste Operand als wahr ausgewertet wird, und der zweite Operand, wenn der erste Operand als falsch ausgewertet wird.

In diesem Fall wird der Ausdruck x or y gibt zurück. x wenn es sich True oder wird bei der Umwandlung in einen booleschen Wert als wahr ausgewertet. Andernfalls gibt er y . In den meisten Fällen erfüllt dies den gleichen Zweck wie der Null-Koalitionsoperator von C, aber denken Sie daran:

42    or "something"    # returns 42
0     or "something"    # returns "something"
None  or "something"    # returns "something"
False or "something"    # returns "something"
""    or "something"    # returns "something"

Wenn Sie Ihre Variable verwenden s um etwas zu halten, das entweder ein Verweis auf die Instanz einer Klasse ist oder None (solange Ihre Klasse keine Mitglieder definiert __nonzero__() y __len__() ), ist es sicher, die gleiche Semantik wie der Null-Koalitionsoperator zu verwenden.

Es kann sogar nützlich sein, diesen Nebeneffekt von Python zu haben. Da Sie wissen, welche Werte zu false ausgewertet werden, können Sie dies nutzen, um den Standardwert auszulösen, ohne dass Sie None (z.B. ein Fehlerobjekt).

In einigen Sprachen wird dieses Verhalten als Elvis Betreiber .

159voto

Hugh Bothwell Punkte 52831

Streng genommen,

other = s if s is not None else "default value"

Ansonsten, s = False werden "default value" was vielleicht nicht beabsichtigt war.

Wenn Sie es kürzer machen wollen, versuchen Sie es:

def notNone(s,d):
    if s is None:
        return d
    else:
        return s

other = notNone(s, "default value")

66voto

mortehu Punkte 3000

Hier ist eine Funktion, die das erste Argument zurückgibt, das nicht None :

def coalesce(*arg):
  return reduce(lambda x, y: x if x is not None else y, arg)

# Prints "banana"
print coalesce(None, "banana", "phone", None)

reduce() könnte unnötigerweise alle Argumente durchlaufen, selbst wenn das erste Argument nicht None Sie können also auch diese Version verwenden:

def coalesce(*arg):
  for el in arg:
    if el is not None:
      return el
  return None

36voto

nurettin Punkte 10395

Falls Sie mehr als eine null-bedingte Operation verketten müssen, wie z.B.:

model?.data()?.first()

Dieses Problem ist nicht leicht zu lösen mit or . Es kann auch nicht gelöst werden mit .get() was einen Wörterbuchtyp oder ähnliches erfordert (und ohnehin nicht verschachtelt werden kann) oder getattr() die eine Ausnahme auslöst, wenn NoneType das Attribut nicht hat.

Der relevante PEP, der das Hinzufügen der Null-Koaleszenz zur Sprache in Betracht zieht, ist PEP 505 und die für das Dokument relevante Diskussion befindet sich in der python-Ideen Thema.

18voto

Craig Punkte 596

Mir ist klar, dass dies bereits beantwortet wurde, aber es gibt noch eine andere Möglichkeit, wenn man mit diktatähnlichen Objekten arbeitet.

Wenn Sie ein Objekt haben, das das sein könnte:

{
   name: {
      first: "John",
      last: "Doe"
   }
}

Sie können verwenden:

obj.get(property_name, value_if_null)

Wie:

obj.get("name", {}).get("first", "Name is missing") 

Durch Hinzufügen von {} als Standardwert, wenn "name" fehlt, wird ein leeres Objekt zurückgegeben und an das nächste get weitergegeben. Dies ist ähnlich wie null-safe-navigation in C#, was wie folgt aussehen würde obj?.name?.first .

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