2015-02-07 20 views
9

Ecco un esempio semplificato del mio problema. Ho pensato che queste funzioni avrebbero esattamente lo stesso comportamento:Comportamento strano: operatore ternario per le funzioni

def f1(l): 
    if type(l[0][0])==list: f=lambda x:x[0][0] 
    else: f=lambda x:x[0] 
    l.sort(key=f,reverse=True) 

def f2(l): 
    f=lambda x:x[0][0] if type(l[0][0])==list else lambda x:x[0] 
    l.sort(key=f,reverse=True) 

l=[[1,2],[3,4]] 

Ma in realtà f1(l) funziona bene quando f2(l) crolla con l'eccezione:

IndexError: list index out of range 

Quindi la domanda è perché è così ed è possibile utilizzare l'operatore ternario che restituisce una delle funzioni?

+1

Questa è una sorta di tangenziale, ma forse questo è uno di quei casi in cui un lambda rende le cose meno facili da leggere, piuttosto che altro. Che ne dici di un 'def getKey (x):' ​​che esamina 'x' e restituisce' x [0] 'o' x [0] [0] 'o quello che ti serve? Quindi 'l.sort (chiave = getKey, reverse = True)'. –

+0

@Asad Sì, è un ottimo punto, anche se potrebbe funzionare un po 'più lentamente rispetto alla versione originale. – Nik

+0

Non sono sicuro di capire perché sarebbe più lento. Evita il sovraccarico di fare una funzione ogni volta che chiami 'f1' o' f2', quindi semmai sarebbe (insignificante) più performante. Non direi che la differenza vale la pena di preoccuparsi in entrambi i casi. –

risposta

8

lambda ha la lowest precedence among operators. Questo è il motivo per cui Python analizza quella linea come

f = lambda x: (x[0][0] if type(l[0][0]) == list else lambda x: x[0]) 

La correzione è quello di avvolgere i singoli lambda s tra parentesi:

f = (lambda x: x[0][0]) if type(l[0][0]) == list else (lambda x: x[0]) 

Detto questo, type(l[0][0]) == list è un pò male, isinstance(l[0][0], list) sarebbe il modo migliore (anche gestisce sottoclassi di list).