Condicionalmente pasa un número arbitrario de argumentos con nombre predeterminados a una función

¿Es posible pasar un número arbitrario de argumentos predeterminados nombrados a una función de Python condicionalmente?

Por ejemplo. hay una función:

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

Ahora, la lógica es que tengo una condición que determina si se debe pasar arg3, puedo hacerlo así:

 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 ) 

    La única forma en que puedo pensar 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 Usa el código que te proporcionaste, o algo como esto:

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

    Esa no sería una syntax de Python válida, tienes que tener algo después de else . Lo que se hace normalmente es:

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

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

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

    Si tienes una función que tiene muchos argumentos por defecto

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

    y quiere pasar diferentes valores a algunos de estos, en función de otra cosa que esté sucediendo en su progtwig, una forma sencilla es usar ** para desempaquetar un diccionario de nombres de argumentos y valores que construyó en función de la lógica de su progtwig.

     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 momento de llamar a su función, si hay mucha lógica que determina lo que entra en su llamada. Deberá tener cuidado si tiene algún argumento que no tenga valores predeterminados, para incluir los valores que está pasando por esos antes de pasar su diccionario.

    Puedes 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() 

    Use esta función para llamar a otra función y use caller.DONT_PASS para especificar los argumentos que no desea pasar.

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

    Tenga en cuenta que este caller() solo admite condicionalmente pasar argumentos de palabras clave. Para admitir los argumentos posicionales, es posible que deba usar la inspect módulo para inspeccionar la función.