Domanda

in c # c'è un operatore null-coalescing (scritto come ??) che consente una facile (corta) controllo nullo durante l'assegnazione:

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

C'è un equivalente Python?

So che posso fare:

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

Ma c'è un modo ancora più breve (dove non ho bisogno di ripetere s)?

È stato utile?

Soluzione

other = s or "some default value"
.

OK, deve essere chiarito come funziona l'operatore or. È un operatore booleano, quindi funziona in un contesto booleano. Se i valori non sono booleani, vengono convertiti in boolean ai fini dell'operatore.

Si noti che l'operatore or non restituisce solo True o FalseTagCode. Invece, restituisce il primo operando se il primo operando valuta il vero, e restituisce il secondo operando se il primo operando valuta false.

In questo caso, l'espressione x or y restituisce x se è True o valuta il vero quando convertito in booleano. Altrimenti, restituisce y. Per la maggior parte dei casi, questo servirà per lo stesso scopo dell'operatore null-coalescente di C♯, ma tieni presente:

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

Se si utilizza la variabile s per tenere utile qualcosa che è un riferimento all'istanza di una classe o None (a condizione che la classe non definisca i membri __nonzero__() e __len__()), è sicuro utilizzare la stessa semantica del Operatore NULL-Coalescing.

In effetti, potrebbe anche essere utile avere questo effetto collaterale di Python. Dal momento che sai quali valori valutano il falso, è possibile utilizzarlo per attivare il valore predefinito senza utilizzare None specificamente (un oggetto di errore, ad esempio).

In alcune lingue questo comportamento è indicato come Elvis operator .

Altri suggerimenti

rigorosamente,

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

In caso contrario, s = False diventerà "default value", che potrebbe non essere quello che è stato inteso.

Se vuoi renderlo più breve, prova:

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

other = notNone(s, "default value")
.

Ecco una funzione che restituirà il primo argomento che non è 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() potrebbe inutilmente iterare su tutti gli argomenti anche se il primo argomento non è None, in modo da poter utilizzare anche questa versione:

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

Mi rendo conto che questo è una risposta, ma c'è un'altra opzione quando hai a che fare con gli oggetti.

Se hai un oggetto che potrebbe essere:

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

Puoi usare:

obj.get(property_name, value_if_null)
.

Come:

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

Aggiungendo {} come valore predefinito, se manca il "nome", un oggetto vuoto viene restituito e passato fino al prossimo GET.Questo è simile a NULL-Safe-Navigation in C #, che sarebbe come obj?.name?.first.

Oltre alla risposta di Juliano sul comportamento di "o": È "veloce"

>>> 1 or 5/0
1
.

Quindi a volte è potrebbe essere un utile collegamento per cose come

object = getCachedVersion() or getFromDB()
.

Per quanto riguarda le risposte di @hugh Bothwell, @.Rortehu e @glglGL.

Setup set di dati per il test

import random

dataset = [random.randint(0,15) if random.random() > .6 else None for i in range(1000)]
.

Definisci implementazioni

def not_none(x, y=None):
    if x is None:
        return y
    return x

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

def coalesce2(*args):
    return next((i for i in args if i is not None), None)
.

FARE FUNZIONE TEST

def test_func(dataset, func):
    default = 1
    for i in dataset:
        func(i, default)
.

Risultati su Mac I7 @ 2.7GHz usando Python 2.7

>>> %timeit test_func(dataset, not_none)
1000 loops, best of 3: 224 µs per loop

>>> %timeit test_func(dataset, coalesce1)
1000 loops, best of 3: 471 µs per loop

>>> %timeit test_func(dataset, coalesce2)
1000 loops, best of 3: 782 µs per loop
.

Chiaramente la funzione not_none risponde correttamente alla domanda dell'OP e gestisce il problema "falsy". È anche il più veloce e più facile da leggere. Se applicazione della logica in molti luoghi, è chiaramente il modo migliore per andare.

Se hai un problema in cui vuoi trovare il 1 ° valore non nullo in un Iterable, allora @ la risposta di Mortehu è la strada da percorrere. Ma è una soluzione a diverso problema che op, sebbene possa gestire parzialmente quel caso. Non può richiedere un valore Iterable e un valore predefinito. L'ultimo argomento sarebbe il valore predefinito restituito, ma non passeresti in unicabile in tal caso così come non è esplicito che l'ultimo argomento sia un valore predefinito da valutare.

Si potrebbe quindi fare sotto, ma userei ancora not_null per il caso di utilizzo a valore singolo.

def coalesce(*args, **kwargs):
    default = kwargs.get('default')
    return next((a for a in arg if a is not None), default)
.

Python has a get function that its very useful to return a value of an existent key, if the key exist;
if not it will return a default value.

def main():
    names = ['Jack','Maria','Betsy','James','Jack']
    names_repeated = dict()
    default_value = 0

    for find_name in names:
        names_repeated[find_name] = names_repeated.get(find_name, default_value) + 1
.

Se non riesci a trovare il nome all'interno del dizionario, restituirà il default_value, Se il nome esiste, aggiungerà qualsiasi valore esistente con 1.

Spero che questo possa aiutare

Le due funzioni di seguito ho trovato molto utile quando si tratta di molti casi di test variabili.

def nz(value, none_value, strict=True):
    ''' This function is named after an old VBA function. It returns a default
        value if the passed in value is None. If strict is False it will
        treat an empty string as None as well.

        example:
        x = None
        nz(x,"hello")
        --> "hello"
        nz(x,"")
        --> ""
        y = ""   
        nz(y,"hello")
        --> ""
        nz(y,"hello", False)
        --> "hello" '''

    if value is None and strict:
        return_val = none_value
    elif strict and value is not None:
        return_val = value
    elif not strict and not is_not_null(value):
        return_val = none_value
    else:
        return_val = value
    return return_val 

def is_not_null(value):
    ''' test for None and empty string '''
    return value is not None and len(str(value)) > 0
.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top