Jaki jest właściwy sposób używania **kwargs
w Pythonie, jeśli chodzi o wartości domyślne?
kwargs
zwraca słownik, ale jaki jest najlepszy sposób na ustawienie wartości domyślnych, czy istnieje? Czy powinienem uzyskać do niego dostęp jako słownik? Używać funkcji get?
class ExampleClass:
def __init__(self, **kwargs):
self.val = kwargs['val']
self.val2 = kwargs.get('val2')
Proste pytanie, ale na które nie mogę znaleźć dobrych zasobów. Ludzie robią to w różny sposób w kodzie, który widziałem i trudno jest wiedzieć, czego użyć.
__init__()
. Czy ktoś może wyjaśnić, dlaczego jest to niepozostawiająca kłótni przestępstwo?self.__dict__update(**kwargs)
może redefiniować metody i powodować inne błędyPodczas gdy większość odpowiedzi mówi, że np.
jest taki sam jak"
to nie jest prawda. W drugim przypadku
f
można wywołać jakof(23, 42)
, podczas gdy pierwszy przypadek przyjmuje tylko nazwane argumenty - bez wywołań pozycyjnych. Często chcesz pozwolić na maksymalną elastyczność abonenta wywołującego, dlatego preferowana jest druga forma, jak twierdzi większość odpowiedzi: ale nie zawsze tak jest. Gdy akceptujesz wiele opcjonalnych parametrów, z których zwykle tylko kilka jest przekazywanych, może być doskonałym pomysłem (unikanie wypadków i nieczytelnego kodu w witrynach połączeń!) Wymuszenie użycia nazwanych argumentów -threading.Thread
to przykład. Pierwszą formą jest sposób implementacji tego w Python 2.Idiom jest tak ważne, że w Pythonie 3 ma teraz specjalną składnię pomocnicze: każdy argument, po jednokrotnym
*
wdef
podpisie jest tylko słowa kluczowe, czyli nie mogą być przekazywane jako argumentu pozycyjnym, ale tylko w nazwie jednego. Tak więc w Python 3 możesz zakodować powyższe jako:Rzeczywiście, w Pythonie 3 możesz nawet mieć argumenty zawierające tylko słowa kluczowe, które nie są opcjonalne (te bez wartości domyślnej).
Jednak Python 2 ma przed sobą długie lata produktywnego życia, więc lepiej nie zapominać o technikach i idiomach, które pozwalają wdrożyć w Pythonie 2 ważne pomysły projektowe, które są bezpośrednio obsługiwane w języku Python 3!
źródło
Sugeruję coś takiego
A następnie użyj wartości w dowolny sposób
dictionaryA.update(dictionaryB)
Dodaje zawartośćdictionaryB
dodictionaryA
nadpisywania żadnych duplikatów kluczy.źródło
for key in options: self.__setattr__(key, options[key])
i jestem gotowy. :)Zrobiłbyś
lub
Jeśli używasz
pop
, możesz sprawdzić, czy wysyłane są fałszywe wartości, i podjąć odpowiednie działania (jeśli istnieją).źródło
.pop
że pomogłoby Ci „sprawdzić, czy przesłano jakieś fałszywe wartości”?kwargs
z jakiegoś powodu.default_value
przekazany? A potem usuwa ten klucz?Używanie ** kwargs i wartości domyślnych jest łatwe. Czasami jednak nie powinieneś używać ** kwargs w pierwszej kolejności.
W tym przypadku tak naprawdę nie najlepiej wykorzystujemy ** kwargs.
Powyżej jest „po co zawracać sobie głowę”? deklaracja. To jest to samo co
Kiedy używasz ** kwargs, masz na myśli, że słowo kluczowe jest nie tylko opcjonalne, ale warunkowe. Istnieją bardziej złożone reguły niż proste wartości domyślne.
Kiedy używasz ** kwargs, zwykle masz na myśli coś podobnego do tego, w którym nie obowiązują proste wartości domyślne.
źródło
Ponieważ
**kwargs
jest używany, gdy liczba argumentów jest nieznana, dlaczego tego nie zrobić?źródło
Oto inne podejście:
źródło
get_form_kwargs()
.). ccbv.co.uk/projects/Django/1.5/django.views.generic.edit/…get_form()
metody wykazuje, w jaki sposób uzyskać argumenty słów kluczowych obszernie o odroczenie innego sposobu (get_form_kwargs
jak wspomniano powyżej). To wystąpienie formularz w następujący sposób:form_class(**self.get_form_kwargs())
.get_form_kwargs()
widok podklasy i dodać / usunąć kwargs na podstawie określonej logiki. Ale to dotyczy samouczka Django.Myślę, że właściwym sposobem używania
**kwargs
w Pythonie, jeśli chodzi o wartości domyślne, jest użycie metody słownikowejsetdefault
, jak podano poniżej:W ten sposób, jeśli użytkownik
args
poda słowo kluczowe „val” lub „val2” w słowie kluczowym , zostanie ono użyte; w przeciwnym razie zostaną użyte ustawione wartości domyślne.źródło
Możesz zrobić coś takiego
źródło
W następstwie sugestii @srhegde o użyciu setattr :
Ten wariant jest przydatny, gdy oczekuje się, że klasa będzie miała wszystkie elementy na naszej
acceptable
liście.źródło
Jeśli chcesz połączyć to z * args, musisz zachować * args i ** kwargs na końcu definicji.
Więc:
źródło
@AbhinavGupta i @Steef zaproponowały użycie
update()
, które okazało się bardzo pomocne przy przetwarzaniu dużych list argumentów:Co jeśli chcemy sprawdzić, czy użytkownik nie przekazał żadnych fałszywych / nieobsługiwanych argumentów? @VayaySajip wskazał, że
pop()
można go użyć do iteracyjnego przetwarzania listy argumentów. Zatem wszelkie pozostałe argumenty są fałszywe. Miły.Oto inny możliwy sposób, aby to zrobić, zachowując prostą składnię użycia
update()
:unknown_args
jestset
zawierający nazwy argumentów, które nie występują w domyślnych.źródło
Innym prostym rozwiązaniem do przetwarzania nieznanych lub wielu argumentów może być:
źródło
** kwargs daje swobodę dodawania dowolnej liczby argumentów słów kluczowych. Można mieć listę kluczy, dla których można ustawić wartości domyślne. Ale ustawienie domyślnych wartości dla nieokreślonej liczby kluczy wydaje się niepotrzebne. Wreszcie ważne może być posiadanie kluczy jako atrybutów instancji. Zrobiłbym to w następujący sposób:
źródło