2010-01-03 12 views
250

C'è un modo per espandere una tupla Python in una funzione, come parametri effettivi?Tuple in espansione in argomenti

Per esempio, ecco expand() fa la magia:

tuple = (1, "foo", "bar") 

def myfun(number, str1, str2): 
    return (number * 2, str1 + str2, str2 + str1) 

myfun(expand(tuple)) # (2, "foobar", "barfoo") 

So che si potrebbe definire come myfunmyfun((a, b, c)), ma naturalmente ci possono essere codice legacy. Grazie

risposta

486

myfun(*tuple) fa esattamente ciò che si richiede.

questione secondaria: Non uso come i dati identificativi dell'utente builtin nomi di tipo quali tuple, list, file, set, e così via - è la pratica orribile e sarà tornare a mordere quando meno te aspettatevi, quindi prendete l'abitudine di attivamente evitando nascondendo i nomi incorporati con i vostri identificatori.

+1

Potrebbe fornire una spiegazione del motivo per cui l'operatore asteriks fa ciò che è stato chiesto? – winklerrr

+1

L'operatore * semplicemente decomprime la tupla e le passa come gli argomenti posizionali della funzione. Vedi di più qui: https://docs.python.org/3/tutorial/controlflow.html#tut-unpacking-arguments –

+0

Si noti che la stessa sintassi può essere utilizzata per liste e tuple. –

12

Dai uno sguardo allo the Python tutorial sezione 4.7.3 e 4.7.4. Si parla di passare le tuple come argomenti.

Vorrei anche prendere in considerazione l'utilizzo di parametri denominati (e il passaggio di un dizionario) invece di utilizzare una tupla e passare una sequenza. Trovo che l'uso di argomenti posizionali sia una cattiva pratica quando le posizioni non sono intuitive o ci sono più parametri.

27

Si noti che è anche possibile espandere parte della lista degli argomenti:

myfun(1, *("foo", "bar")) 
+11

Sembra che si possa fare solo se la tupla espansa si trova dopo gli argomenti normalmente forniti - l'interprete non gli piace quando faccio questo: 'some_func (* tuple_of_stuff, another_argument)' – Quackmatic

+3

@Quackmatic Avere la tupla espansa in qualsiasi posizione sembra funzionare bene in Python 3.5.1 – River

2

Questo è il metodo di programmazione funzionale. Alza la funzione di espansione tupla di zucchero sintassi: utilizzo

apply_tuple = lambda f, t: f(*t)

Esempio:

from toolz import * 
from operator import add, eq 

apply_tuple = curry(apply_tuple) 

thread_last(
    [(1,2), (3,4)], 
    (map, apply_tuple(add)), 
    list, 
    (eq, [3, 7]) 
) 
# Prints 'True' 

curry redefiniton di apply_tuple fa risparmiare un sacco di chiamate partial nel lungo periodo.

+1

Questo non è utile per un principiante. Usa i moduli di terze parti e fa altre cose confuse ... – gberger

+0

gberger, 'lambda f, t: f (* t)' non usa i moduli di terze parti e io sono un principiante di Python e questo è utile per me. Questo è un approccio puramente funzionale. Se non usi questo stile, questa risposta non fa per te. –

+0

toolz è di terze parti, è ciò che intendevo – gberger

0

Ho riscontrato problemi simili e ho creato questa funzione che espande la funzione fissa. Spero che questo ti aiuti.

def run_argtup(func, argvalues): 
    """ 
    Execute any functions with their arguments in tuple. 

    :param func: 
    :param argvalues: 
    :return: 
    """ 
    argnames = get_func_argnames(func) 
    if len(argnames) != len(argvalues): 
     raise ValueError("Length of args doens't match.") 
    for argn, argv in zip(argnames, argvalues): 
     exec('{}=argv'.format(argn)) 
    return eval('func(%s, %s)' % argnames)