C'è un modo per passare parametri opzionali a una funzione?


133

Esiste un modo in Python per passare parametri opzionali a una funzione mentre la chiama e nella definizione della funzione hanno del codice basato su "solo se viene passato il parametro opzionale"

Risposte:


115

La documentazione di Python 2, 7.6. Le definizioni delle funzioni offrono un paio di modi per rilevare se un chiamante ha fornito un parametro opzionale.

Innanzitutto, è possibile utilizzare una sintassi di parametro formale speciale *. Se la definizione della funzione ha un parametro formale preceduto da un singolo *, Python popola quel parametro con tutti i parametri posizionali che non corrispondono ai parametri formali precedenti (come tupla). Se la definizione della funzione ha un parametro formale preceduto da **, Python popola quel parametro con tutti i parametri di parole chiave che non corrispondono ai parametri formali precedenti (come un dict). L'implementazione della funzione può verificare il contenuto di questi parametri per eventuali "parametri opzionali" del tipo desiderato.

Per esempio, ecco una funzione opt_funche prende due parametri posizionali x1e x2, e cerca un altro parametro parola chiave denominata "optional".

>>> def opt_fun(x1, x2, *positional_parameters, **keyword_parameters):
...     if ('optional' in keyword_parameters):
...         print 'optional parameter found, it is ', keyword_parameters['optional']
...     else:
...         print 'no optional parameter, sorry'
... 
>>> opt_fun(1, 2)
no optional parameter, sorry
>>> opt_fun(1,2, optional="yes")
optional parameter found, it is  yes
>>> opt_fun(1,2, another="yes")
no optional parameter, sorry

In secondo luogo, è possibile fornire un valore di parametro predefinito di un valore come quello Noneche un chiamante non userebbe mai. Se il parametro ha questo valore predefinito, sai che il chiamante non ha specificato il parametro. Se il parametro ha un valore non predefinito, sai che proviene dal chiamante.


7
positional_parametersè una tupla e keyword_parametersun dizionario.
Cees Timmerman,

In che modo Python distingue formal parameters preceded by * (come si chiama?) Da un keyword parameter? Come ho capito, i parametri delle parole chiave vengono specificati usando l' =operatore nella chiamata della funzione (quindi opt_fun(1,2, optional="yes")fornisce un argomento della parola chiave "yes" per una funzione che anticipa, ma non richiede necessariamente, il parametro option).
Minh Tran,

D'altra parte, ho capito formal parameters preceded by * semplicemente "gli argomenti forniti dal chiamante che non corrispondono agli argomenti posizionali che precedono qualsiasi argomento di parole chiave". Ad esempio, in opt_fun(1,2, "blah", 3.14, mykey="yes", myyear="2018"), "blah"e 3.14sono forma arguments preceded by *perché si trova tra i due argomenti posizionali e l'argomento che utilizza il =segno. La tupla risultante positional_parametersarebbe la duple: ("blah", 3.14). È corretto?
Minh Tran,

@MinhTran, le domande nei commenti non sono il modo migliore per ottenere una risposta in Stack Overflow. È molto meglio fare clic sul grande pulsante blu "Poni domanda" e scrivere la tua richiesta come "Domanda" alla quale gli altri possono "rispondere". Ma per aiutarti, a) nota che ho scritto " parameter" non " parameters" per " preceded by *". La lingua ne consente solo una *identifiernell'elenco dei parametri. b) leggi docs.python.org/2/reference/… , c) leggi docs.python.org/2/reference/expressions.html#calls . Spiacente, a corto di caratteri consentiti in questo commento.
Jim DeLaHunt,

81
def my_func(mandatory_arg, optional_arg=100):
    print(mandatory_arg, optional_arg)

http://docs.python.org/2/tutorial/controlflow.html#default-argument-values

Lo trovo più leggibile dell'uso **kwargs.

Per determinare se è stato passato un argomento, utilizzo un oggetto utility personalizzato come valore predefinito:

MISSING = object()

def func(arg=MISSING):
    if arg is MISSING:
        ...

-Grazie, c'è un modo per specificare il valore predefinito di questo parametro come un'altra variabile nel codice?
user1795998

sì. default_value=100; def my_func(mandatory_argument, optional_argument_with_default_value=default_value): ...
Warvariuc,

Questo sembra mostrare come usare parametri opzionali, ma non come testare se uno è passato, che è ciò che l'OP sta chiedendo.
Mawg dice di ripristinare Monica

4
Nella maggior parte dei casi questa è la soluzione più semplice e diretta di quella di Jim. Se si imposta il valore predefinito su Nessuno, è possibile verificare se il parametro è stato passato o meno. L'unico caso in cui la soluzione di Jim è migliore è se è importante distinguere tra passare None come argomento e non passare affatto un argomento.
Arnon Axelrod,

19
def op(a=4,b=6):
    add = a+b
    print add

i)op() [o/p: will be (4+6)=10]
ii)op(99) [o/p: will be (99+6)=105]
iii)op(1,1) [o/p: will be (1+1)=2]
Note:
 If none or one parameter is passed the default passed parameter will be considered for the function. 

1
C'è un modo per passare solo il secondo parametro (b) e non il primo (a)?
Djidiouf,

4
@Djidiouf Sì, c'èop(b=2)
Jürg Merlin Spaak il

7

Se si desidera assegnare un valore predefinito a un parametro, assegnare un valore in (). come (x = 10). Ma prima è importante l'argomento obbligatorio, quindi il valore predefinito.

per esempio.

(y, x = 10)

ma

(x = 10, y) è errato


Grazie, c'è un modo per specificare il valore predefinito di questo parametro come un'altra variabile nel codice?
user1795998

Sì, puoi usare qualcosa chiamato *arg **kargcome argomenti di funzione. cerca su google.
Accusa il

Questo sembra mostrare come usare parametri opzionali, ma non come testare se uno è passato, che è ciò che l'OP sta chiedendo.
Mawg dice di ripristinare Monica

2

È possibile specificare un valore predefinito per l'argomento facoltativo con qualcosa che non passerebbe mai alla funzione e verificarlo con l' isoperatore:

class _NO_DEFAULT:
    def __repr__(self):return "<no default>"
_NO_DEFAULT = _NO_DEFAULT()

def func(optional= _NO_DEFAULT):
    if optional is _NO_DEFAULT:
        print("the optional argument was not passed")
    else:
        print("the optional argument was:",optional)

quindi finché non lo fai func(_NO_DEFAULT), puoi essere in grado di rilevare con precisione se l'argomento è stato passato o meno e, diversamente dalla risposta accettata, non devi preoccuparti degli effetti collaterali della notazione **:

# these two work the same as using **
func()
func(optional=1)

# the optional argument can be positional or keyword unlike using **
func(1) 

#this correctly raises an error where as it would need to be explicitly checked when using **
func(invalid_arg=7)

Fallo e basta _NO_DEFAULT = object().
Aran-Fey,

Ne vale la pena 2 linee extra per dare una migliore introspezione. Con questo, se corri, help(func)avrai un'idea più chiara di come l'argomento viene interpretato se non trasmesso esplicitamente.
Tadhg McDonald-Jensen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.