Czy istnieje prosty sposób w Pythonie, aby sprawdzić, czy wartość opcjonalnego parametru pochodzi od jego wartości domyślnej, czy też użytkownik ustawił go jawnie przy wywołaniu funkcji?Python: jak sprawdzić, czy opcjonalny parametr funkcji jest ustawiony
Odpowiedz
Niezupełnie. Standardowym sposobem jest użycie wartości domyślnej, której użytkownik nie powinien przejść, np. object
instancja:
DEFAULT = object()
def foo(param=DEFAULT):
if param is DEFAULT:
...
Zazwyczaj można po prostu użyć None
jako wartość domyślną, jeśli to nie ma sensu, jako wartość użytkownik chciałby przekazać.
Alternatywą jest użycie kwargs
:
def foo(**kwargs):
if 'param' in kwargs:
param = kwargs['param']
else:
...
Jednak jest zbyt rozwlekły i sprawia, że funkcja trudniejsze do wykorzystania jako jego dokumentacja nie będzie automatycznie zawierać parametr param
.
dziękuję, myślę, że będę trzymać się czeku na Brak – Matthias
Widziałem również kilka osób korzysta z wbudowanego Ellipsis dla miejsc, gdzie jest to potrzebne i Brak jest uważane za prawidłowe wejście. Jest to zasadniczo takie samo jak w pierwszym przykładzie. – GrandOpener
Zgadzam się z komentarzem Wrażliwości. Ale można sprawdzić w następujący sposób:
def function(arg1,...,**optional):
if 'optional_arg' in optional:
# user has set 'optional_arg'
else:
# user has not set 'optional_arg'
optional['optional_arg'] = optional_arg_default_value # set default
Wierzę, że opcjonalny parametr jest coś jak "def func (opcjonalne = wartość)' nie '** kwargs' –
To jest coś, co jest nieco otwarte na interpretację. Jaka jest rzeczywista różnica między argumentem a wartością domyślną a argumentem słowa kluczowego? Oba wyrażane są przy użyciu tej samej składni "keyword = value". – isedev
Nie zgadzam się, ponieważ cel opcjonalnych parametrów i '** kwargs' jest nieco inny. P.S. nie ma problemu około -1 :) I moje -1 dla ciebie było przypadkowe :) –
Trochę dziwaczne podejście byłoby:
które wyjścia:
passed default
z
passed different
b
not passed
z
Teraz, jak już wspomniano, jest dość kapryśny , ale spełnia swoją funkcję. Jest to jednak całkowicie nieczytelne i podobnie do ecatmur 's suggestion nie będzie automatycznie dokumentowane.
Możesz chcieć dołączyć zachowanie 'check_f ('z')', które jest również, jak mówisz, dziwaczne. –
@ MichaelJ.Barber Dobra uwaga. Będziesz musiał zrobić "magię" również z * args. Chodzi mi jednak o to, że jest to możliwe, ale potrzebuję teraz, czy wartość domyślna jest przekazywana, czy nie, jest złym projektem. – dmg
Następujący dekorator funkcji, explicit_checker
, tworzy zestaw nazw parametrów wszystkich podanych parametrów jawnie. Dodaje wynik jako dodatkowy parametr (explicit_params
) do funkcji. Po prostu wykonaj 'a' in explicit_params
, aby sprawdzić, czy parametr a
jest jawnie podany.
def explicit_checker(f):
varnames = f.func_code.co_varnames
def wrapper(*a, **kw):
kw['explicit_params'] = set(list(varnames[:len(a)]) + kw.keys())
return f(*a, **kw)
return wrapper
@explicit_checker
def my_function(a, b=0, c=1, explicit_params=None):
print a, b, c, explicit_params
if 'b' in explicit_params:
pass # Do whatever you want
my_function(1)
my_function(1, 0)
my_function(1, c=1)
Czasami używam uniwersalnego unikalnego ciągu (jak UUID).
import uuid
DEFAULT = uuid.uuid4()
def foo(arg=DEFAULT):
if arg is DEFAULT:
# it was not passed in
else:
# it was passed in
W ten sposób użytkownik może nawet nie domyślić domyślny gdyby próbowali więc mogę być pewni, że gdy widzę, że wartość dla arg
, nie została podjęta w.
To trochę hack, ale zwięzłe i skuteczne ... – F1Rumors
Obiekty Pythona są referencjami, możesz po prostu użyć 'object()' zamiast 'uuid4()' - to wciąż wyjątkowa _instance_, która jest tym, czym jest 'is' czeki –
Widziałem ten wzór kilka razy (na przykład biblioteka unittest
, py-flags
, jinja
):
class Default:
def __repr__(self):
return "DEFAULT"
DEFAULT = Default()
... lub równowartość jednego-liner ...:
DEFAULT = type('Default',(), { '__repr__': lambda x: 'DEFAULT' })()
przeciwieństwie DEFAULT = object()
, to pomaga typu sprawdzanie i dostarcza informacji w przypadku wystąpienia błędów - często albo reprezentacja string ("DEFAULT"
) lub nazwa klasy ("Default"
) stosuje się w komunikaty o błędach.
Dlaczego to ma znaczenie? – Volatility
Bo chcę to sprawdzić w tej funkcji oczywiście :) – Matthias
Po prostu użyj 'None' jako domyślnego i sprawdź to.Jeśli naprawdę możesz skonfigurować ten test, możesz również wykluczyć jakąkolwiek możliwość, aby użytkownik jawnie przekazał wartość, która wywołuje domyślne zachowanie. –