2011-01-12 12 views
8

¿Es posible pasar un número arbitrario de argumentos predeterminados con nombre a una función de Python condicionalmente?Condicionalmente se pasa un número arbitrario de argumentos con nombre predeterminado a una función

Por ej. hay una función:

def func(arg, arg2='', arg3='def') 

Ahora lógica es que tengo una condición que determina si arg3 necesita ser aprobada, puedo hacerlo de esta manera:

if condition == True: 
    func('arg', arg2='arg2', arg3='some value') 
else: 
    func('arg', arg2='arg2') 

La pregunta es, ¿puedo tener una taquigrafía como:

func('arg', 'arg2', 'some value' if condition == True else # nothing so default gets picked 
) 

Respuesta

5

La única manera que se me ocurre sería

func("arg", "arg2", **({"arg3": "some value"} if condition == True else {})) 

o

func("arg", "arg2", *(("some value",) if condition == True else())) 

pero por favor, no hagas esto. Utilice el código que ya ha proporcionado usted mismo, o algo como esto:

if condition: 
    arg3 = "some value", 
else: 
    arg3 =() 
func("arg", "arg2", *arg3) 
+2

¿Qué tiene contra ** y *? – Erin

+2

Nada en contra de '*' y '**'. Solo creo que el código original es más legible. Creo que no me gusta 'a if c else b'. –

+0

Alternativamente, podría usarse alguna lógica condicional (fuera de la llamada a función) para construir un diccionario de argumentos.Luego podrían pasar con '**'. Esto se mantiene legible con una mayor cantidad de argumentos. – Wilduck

8

que no sería válida la sintaxis de Python que tiene que tener algo después de else. Lo que se hace normalmente es:

func('arg', 'arg2', 'some value' if condition else None) 

y definición de la función se cambia en consecuencia:

def func(arg, arg2='', arg3=None): 
    arg3 = 'def' if arg3 is None else arg3 
1

Si usted tiene una función que tiene una gran cantidad de argumentos por defecto

def lots_of_defaults(arg1 = "foo", arg2 = "bar", arg3 = "baz", arg4 = "blah"): 
    pass 

y que desea Pase diferentes valores a algunos de estos, en función de algo más que esté sucediendo en su programa, una forma simple es usar ** para descomprimir un diccionario de nombres de argumentos y valores que construyó bas ed en su lógica de programa.

different_than_defaults = {} 
if foobar: 
    different_than_defaults["arg1"] = "baaaz" 
if barblah: 
    different_than_defaults["arg4"] = "bleck" 

lots_of_defaults(**different_than_defaults) 

Esto tiene la ventaja de no obstruir su código en el punto de llamar a su función, si hay una gran cantidad de lógica para determinar lo que pasa en su llamada. Deberá tener cuidado si tiene argumentos que no tienen valores predeterminados, para incluir los valores que está aprobando antes de pasar su diccionario.

0

puede escribir una función auxiliar

def caller(func, *args, **kwargs): 
    return func(*args, **{k:v for k,v in kwargs.items() if v != caller.DONT_PASS}) 
caller.DONT_PASS = object() 

Utilice esta función para llamar a otra función y utilizar caller.DONT_PASS para especificar los argumentos que usted no quiere pasar.

caller(func, 'arg', 'arg2', arg3 = 'some value' if condition else caller.DONT_PASS) 

Tenga en cuenta que este caller() único apoyo que pasa condicionalmente argumentos de palabra clave. Para admitir los argumentos posicionales, es posible que necesite usar el módulo inspect para inspeccionar la función.

Cuestiones relacionadas