2011-01-12 7 views
8

È possibile passare un numero arbitrario di argomenti predefiniti denominati a una funzione Python in modo condizionale?Condizionalmente il numero arbitrario di argomenti denominati predefiniti a una funzione

Ad es. c'è una funzione:

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

Ora la logica è che ho una condizione che determina se arg3 deve essere passato, posso fare in questo modo:

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

domanda è, posso avere una scorciatoia come:

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

risposta

5

L'unico modo che posso pensare sarebbe

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

o

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

ma per favore non fare questo. Utilizzare il codice che hai fornito voi stessi, o qualcosa di simile:

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

Cos'è che hai contro ** e *? – Erin

+2

Niente contro '*' e '**'. Penso solo che il codice originale sia più leggibile. Penso che non mi piace 'a if c else b'. –

+0

In alternativa, è possibile utilizzare una logica condizionale (al di fuori della chiamata di funzione) per costruire un dizionario di argomenti.Potrebbero essere passati con '**'. Questo rimane leggibile con un numero maggiore di argomenti. – Wilduck

8

Che non sarebbe la sintassi Python valido bisogna avere qualcosa dopo else. Quel che è fatto è normalmente:

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

e definizione di funzione verrà modificata di conseguenza:

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

Se si dispone di una funzione che ha un sacco di argomenti di default

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

e si vuole passare valori diversi ad alcuni di questi, sulla base di qualcos'altro che sta succedendo nel tuo programma, un modo semplice è usare ** per decomprimere un dizionario di nomi di argomenti e valori che hai costruito bas sulla logica del tuo programma.

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

lots_of_defaults(**different_than_defaults) 

Questo ha il vantaggio di non intasare il codice al punto di chiamare la funzione, se c'è un sacco di logica per determinare ciò che accade nella vostra chiamata. Dovrai stare attento se hai argomenti che non hanno valori predefiniti, per includere i valori che stai passando per quelli prima di passare il tuo dizionario.

0

è possibile scrivere una funzione di supporto

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

Usare questa funzione per chiamare un'altra funzione e utilizzare caller.DONT_PASS per specificare gli argomenti che non si desidera passare.

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

Si noti che questo caller() unico sostegno condizionatamente passando argomenti chiave. Per supportare argomenti posizionali, potrebbe essere necessario utilizzare il modulo inspect per ispezionare la funzione.

Problemi correlati