2010-01-03 16 views
250

¿Hay alguna forma de expandir una tupla de Python en una función, como parámetros reales?Expandir tuplas en argumentos

Por ejemplo, aquí expand() hace la magia:

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

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

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

Sé que se podría definir como myfunmyfun((a, b, c)), pero por supuesto puede haber código heredado. Gracias

Respuesta

486

myfun(*tuple) hace exactamente lo que usted solicita.

cuestión secundaria: No uso como sus identificadores BuiltIn nombres de tipos tales como tuple, list, file, set, y así sucesivamente - Es una práctica horrible y se volver y morderte cuando menos lo espera, así que adquiera el hábito de activamente evitando ocultando nombres incorporados con sus propios identificadores.

+1

¿Podría proporcionar una explicación de por qué el operador asteriks hace lo que se le pidió? – winklerrr

+1

El operador * simplemente descomprime la tupla y la pasa como argumentos posicionales a la función. Consulte más aquí: https://docs.python.org/3/tutorial/controlflow.html#tut-unpacking-arguments –

+0

Tenga en cuenta que la misma sintaxis se puede utilizar para listas y tuplas. –

12

Eche un vistazo a the Python tutorial sección 4.7.3 y 4.7.4. Habla de pasar tuplas como argumentos.

También consideraría usar parámetros con nombre (y pasar un diccionario) en lugar de usar una tupla y pasar una secuencia. Encuentro que el uso de argumentos posicionales es una mala práctica cuando las posiciones no son intuitivas o hay múltiples parámetros.

27

Tenga en cuenta que también se puede ampliar parte de la lista de argumentos:

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

Parece que solo puede hacer esto si la tupla expandida está después de los argumentos proporcionados normalmente; al intérprete no le gusta cuando hago esto: 'some_func (* tuple_of_stuff, another_argument)' – Quackmatic

+3

@Quackmatic Tener la tupla expandida en cualquier la ubicación parece funcionar bien en Python 3.5.1 – River

2

Este es el método de programación funcional. Se levanta la característica de expansión tupla de azúcar sintaxis: uso

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

Ejemplo:

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 de apply_tuple ahorra mucho partial llamadas en el largo plazo.

+1

Esto no es útil para un principiante. Utiliza módulos de terceros y hace otras cosas confusas ... – gberger

+0

gberger, 'lambda f, t: f (* t)' no usa módulos de terceros y yo soy un principiante de Python y esto es útil para mí. Este es un enfoque funcional puro. Si no usa este estilo, esta respuesta no es para usted. –

+0

toolz es de terceros, es lo que quise decir – gberger

0

Me encontré con un problema similar y creé esta función que expande la función fija. Espero que esto ayude.

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)