def f1(n): #accepts one argument
pass
def f2(): #accepts no arguments
pass
FUNCTION_LIST = [(f1,(2)), #each list entry is a tuple containing a function object and a tuple of arguments
(f1,(6)),
(f2,())]
for f, arg in FUNCTION_LIST:
f(arg)
La tercera ronda de tiempo en el ciclo, intenta pasar una tupla de argumentos vacía a una función que no acepta argumentos. Da el error TypeError: f2() takes no arguments (1 given)
. Las dos primeras llamadas funcionan correctamente: se pasa el contenido de la tupla, no la tupla misma.Python - lista de tuplas de función/argumento
Deshacerse de la tupla vacía de argumentos en la entrada de la lista infractor no resuelve el problema:
FUNCTION_LIST[2] = (f2,)
for f,arg in FUNCTION_LIST:
f(arg)
resultados en ValueError: need more than 1 value to unpack
.
También he intentado iterar sobre el índice en lugar de los elementos de la lista.
for n in range(len(FUNCTION_LIST)):
FUNCTION_LIST[n][0](FUNCTION_LIST[n][1])
Esto le da al mismo TypeError
en el primer caso, y IndexError: tuple index out of range
cuando la tercera entrada de la lista es (f2,)
.
Finalmente, la notación de asterisco tampoco funciona. Esta vez los errores en la llamada a f1
:
for f,args in FUNCTION_LIST:
f(*args)
da TypeError: f1() argument after * must be a sequence, not int
.
Me he quedado sin cosas que probar. Sigo pensando que el primero debería funcionar. ¿Alguien puede señalarme en la dirección correcta?
Gracias por la gran respuesta.Pregunta del corolario: ¿es posible realizar operaciones sobre el valor de retorno de las funciones? Digamos que quería duplicar la primera entrada: 'FUNCTION_LIST = [(f1 * 2, (2)), (f1, (6)), (f2,())]' no funcionaría, lo haría, porque estarías tratando de aplicar el operador de multiplicación a una función _objeto_, no el valor devuelto por la función. –
Relacionado: ¿es posible llamar a otras funciones en los argumentos tuple, que se evaluarían cuando se llame a la función? 'FUNCTION_LIST = [(f1, (time.time(),)), (f1, (6)), (f2,())]' no me daría algo dependiente del tiempo, porque la llamada al tiempo. time() se evaluaría cuando la lista se rellene. –
@poorsod: para la ejecución retrasada, debe definir las funciones que hacen lo que quiere. Por ejemplo 'def double_f1 (x): return 2 * f1 (x)' o 'def f1_time(): return f1 (time.time)'. En algunos casos, puede salirse con la suya con las funciones 'lambda', pero yo recomendaría utilizarlo con moderación. –