Ignora il valore di ritorno multiplo di Python


274

Supponiamo che io abbia una funzione Python che restituisce più valori in una tupla:

def func():
    return 1, 2

C'è un buon modo per ignorare uno dei risultati piuttosto che semplicemente assegnarlo a una variabile temporanea? Di 'che se fossi interessato solo al primo valore, c'è un modo migliore di questo:

x, temp = func()

2
Anch'io mi sono incuriosito di questo che deriva dalla nozione simile di Matlab di Ignore Function Outputs in cui usano ~come sintassi per ignorare una particolare variabile di ritorno
jxramos,

3
Hai selezionato la risposta sbagliata come soluzione
AGP

Risposte:


242

Una convenzione comune è usare un "_" come nome variabile per gli elementi della tupla che si desidera ignorare. Per esempio:

def f():
    return 1, 2, 3

_, _, x = f()

89
-1: questa "convenzione" fa schifo quando aggiungi la funzionalità gettext al codice di qualcun altro (che definisce una funzione chiamata "_"), quindi dovrebbe essere vietata
nosklo,

27
Un buon punto - sebbene sia discutibile se l'insistenza di gettext sull'installazione di una funzione chiamata " " sia una buona idea. Personalmente, lo trovo un po 'brutto. Indipendentemente da ciò, l'uso di " " come variabile usa e getta è molto diffuso.
Brian Clapper,

25
-1: _ significa "ultimo output" in IPython. Non assegnerei mai qualcosa ad esso.
endolith

20
Ok, non ho notato l'io - grazie per il riferimento. IMHO non puoi aspettarti che gli altri non usino una variabile solo perché un'app Python definisce il suo uso magico per essa.
Draemon,

8
alcuni IDE come PyDev ti daranno un avvertimento, perché hai variabili non utilizzate.
teeks99,

595

È possibile utilizzare x = func()[0]per restituire il primo valore, x = func()[1]per restituire il secondo e così via.

Se vuoi ottenere più valori contemporaneamente, usa qualcosa di simile x, y = func()[2:4].


92
Questa dovrebbe essere la risposta accettata. Puoi anche usare cose come func()[2:4]se desideri solo alcuni dei valori di ritorno.
endolith

11
Non chiama la funzione più volte: >>> def test (): ... print "qui" ... return 1,2,3 ... >>> a, b = test () [: 2 ] qui [modifica: mi dispiace che il codice non sia arrivato, a differenza di una riga nei commenti. Per quelli che non hanno familiarità >>> e ... sono l'inizio di una nuova linea nella shell di pitone]
teeks99

32
@TylerLong: Penso che _, _, _, _, _, _, _, _, _, _, _, _, _, a, _, _, _, _, _, _, _, _, _, _, _, b, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, c, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, d, _, _, _, _, _, _, _, _, e, _ = func()sia meno chiaro che chiamare la funzione più volte, ma questa è solo la mia opinione. Se la tua funzione restituisce così tanti elementi, penso che sarebbe preferibile usare numpy:a, b, c, d, e = func()[[13, 25, 58, 89, 98]]
endolith,

24
@endolith Penso che sia meglio e non abbia bisogno di intorpidimento e non abbia bisogno di chiamare func () più volte: result = func() a = result[13] b = result[25]...
Tyler Long

3
Questo stile non è bello quando si desidera ignorare uno o alcuni valori in mezzo, ad esempiox, __, y = func()
ndemou

96

Se stai usando Python 3, puoi usare la stella prima di una variabile (sul lato sinistro di un compito) per avere un elenco in decompressione.

# Example 1: a is 1 and b is [2, 3]

a, *b = [1, 2, 3]

# Example 2: a is 1, b is [2, 3], and c is 4

a, *b, c = [1, 2, 3, 4]

# Example 3: b is [1, 2] and c is 3

*b, c = [1, 2, 3]       

# Example 4: a is 1 and b is []

a, *b = [1]

2
È inoltre possibile utilizzare a, *_ = f()per ignorare il numero arbitrario di valori restituiti dopo a.
THN

21

Ricorda, quando restituisci più di un oggetto, stai davvero restituendo una tupla. Quindi puoi fare cose come questa:

def func():
    return 1, 2

print func()[0] # prints 1
print func()[1] # prints 2

17

La pratica comune è usare la variabile dummy _(singolo trattino basso), come molti hanno indicato qui prima.

Tuttavia, per evitare collisioni con altri usi di quel nome di variabile (vedi questa risposta) potrebbe essere una buona pratica usare __(doppio trattino basso) invece come variabile usa e getta, come indicato da ncoghlan . Per esempio:

x, __ = func()

Non è affatto una cattiva idea. Ma poi '_ _' dichiarerebbe una variabile nello spazio dei nomi. Considerando che, "_" non dichiara se non specificamente utilizzato sul lato sinistro della dichiarazione di assegnazione come sopra (ad esempio:) a, _, _ = 1,8,9. Fino a quel momento, memorizza il risultato dell'ultima istruzione eseguita che, se si desidera catturare, normalmente si utilizza una variabile per memorizzare quel valore. Ed è per questo che '_' è il nome della variabile suggerito per catturare i valori spazzatura. I valori '_' vengono sovrascritti subito dopo l'esecuzione di un'altra istruzione. In caso di '_ _', il valore rimarrebbe lì fino a quando GC non lo pulirà.
Archit Kapoor,

16

Tre semplici scelte.

evidente

x, _ = func()

x, junk = func()

orrendo

x = func()[0]

E ci sono modi per farlo con un decoratore.

def val0( aFunc ):
    def pick0( *args, **kw ):
        return aFunc(*args,**kw)[0]
    return pick0

func0= val0(func)

5
Preferisco davvero la _variabile. È molto ovvio che stai ignorando un valore
Claudiu,

21
I tuoi esempi sono al contrario. x, _ = func()è orribile ed x = func()[0]è ovvio. Assegnare a una variabile e non utilizzarla? La funzione sta restituendo una tupla; indicizzalo come una tupla.
endolito il

6
Nei linguaggi di corrispondenza dei modelli, da cui Python ha derivato questo modello, il metodo "ovvio" è davvero ovvio, non orribile e canonico. Sebbene, in tali lingue, il carattere jolly sia una funzionalità del linguaggio supportato mentre in Python è una variabile reale e viene associata, il che è un po 'sgradevole.
Joe,

4
Per List Processing lingue, da cui Python deriva ;), elenco di accesso come a[0], a[:](lista di copia), a[::2](ogni due elementi), e a[i:] + a[:i](ruotare un elenco), sono infatti, anche ovvio e canonica.
cod3monk3y,

7

La soluzione migliore probabilmente è nominare le cose invece di restituire tuple insignificanti. A meno che non ci sia della logica dietro l'ordine degli articoli restituiti.

def func():
    return {'lat': 1, 'lng': 2}

latitude = func()['lat']

Puoi anche usare namedtuple se desideri aggiungere ulteriori informazioni su ciò che stai restituendo (non è solo un dizionario, si tratta di coordinate):

from collections import namedtuple 

Coordinates = namedtuple('Coordinates', ['lat', 'lng'])

def func():
    return Coordinates(lat=1, lng=2)

latitude = func().lat

Se gli oggetti all'interno del tuo dizionario / tupla sono strettamente legati, potrebbe essere una buona idea persino definire una classe per esso. In questo modo sarai anche in grado di definire l'interazione tra oggetti di questo tipo e dare un'API su come lavorare con essi. Una domanda naturale che segue: quando dovrei usare le classi in Python? .


4

Questa mi sembra la scelta migliore:

val1, val2, ignored1, ignored2 = some_function()

Non è criptico o brutto (come il metodo func () [indice]), e afferma chiaramente il tuo scopo.


4

Questa non è una risposta diretta alla domanda. Piuttosto risponde a questa domanda: "Come faccio a scegliere un output di funzione specifica tra molte opzioni possibili?".

Se sei in grado di scrivere la funzione (cioè, non è in una libreria che non puoi modificare), quindi aggiungi un argomento di input che indichi ciò che desideri dalla funzione. Renderlo un argomento denominato con un valore predefinito, quindi nel "caso comune" non è nemmeno necessario specificarlo.

    def fancy_function( arg1, arg2, return_type=1 ):
        ret_val = None
        if( 1 == return_type ):
            ret_val = arg1 + arg2
        elif( 2 == return_type ):
            ret_val = [ arg1, arg2, arg1 * arg2 ]
        else:
            ret_val = ( arg1, arg2, arg1 + arg2, arg1 * arg2 ) 
        return( ret_val )

Questo metodo fornisce alla funzione "avviso avanzato" per quanto riguarda l'output desiderato. Di conseguenza può saltare l'elaborazione non necessaria e fare solo il lavoro necessario per ottenere l'output desiderato. Anche perché Python esegue la digitazione dinamica, il tipo restituito può cambiare. Nota come l'esempio restituisce uno scalare, un elenco o una tupla ... qualunque cosa ti piaccia!


2

Se questa è una funzione che usi sempre, ma scarti sempre il secondo argomento, direi che è meno complicato creare un alias per la funzione senza usare il secondo valore restituito lambda.

def func():
    return 1, 2

func_ = lambda: func()[0] 

func_()  # Prints 1 

2

Quando hai molti output da una funzione e non vuoi chiamarla più volte, penso che il modo più chiaro per selezionare i risultati sarebbe:

results = fct()
a,b = [results[i] for i in list_of_index]

Come esempio minimo di lavoro, dimostrando anche che la funzione viene chiamata una sola volta:

def fct(a):
    b=a*2
    c=a+2
    d=a+b
    e=b*2
    f=a*a
    print("fct called")
    return[a,b,c,d,e,f]

results=fct(3)
> fct called

x,y = [results[i] for i in [1,4]]

E i valori sono come previsto:

results
> [3,6,5,9,12,9]
x
> 6
y
> 12

Per comodità, è possibile utilizzare anche gli indici dell'elenco Python:

x,y = [results[i] for i in [0,-2]]

Restituisce: a = 3 eb = 12

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.