Czy ** kwargs jest antypoterem?

16

W naszej wewnętrznej bazie kodów znajduje się dużo kodu, który wywołuje nasze biblioteki wewnętrznie - biblioteki te często mają wiele argumentów (myśl matplotlib), a nasz kod często wykonuje tylko określone zadanie i po prostu przekazuje **kwargskolejną wywoływaną funkcję.

Na przykład:

def our_method(dataframe, **kwargs):
    result = do_something_with_data(dataframe)
    external_module.draw(result, **kwargs)

Chociaż **kwargsuniemożliwia nam powtarzanie wszystkich parametrów w naszej deklaracji metody, powoduje również, że niezwykle nieprzejrzyste są argumenty, które są prawidłowe podczas wywoływania our_method- muszę wiedzieć, która metoda jest wywoływana, czego często nie chcę wiedzieć.

Jakie jest twoje zdanie?

Christian Sauer
źródło

Odpowiedzi:

16

W jaki sposób Twój kod jest używany przez programistów? Innymi słowy, co dokładnie robią, aby określić, które argumenty należy zastosować i jak?

  • Jeśli opierają się na dokumentacji generowanej automatycznie z twojego kodu, a generator nie ma pojęcia, co z tym zrobić **kwargs, jest to rzeczywiście problematyczne. Zamiast znajdować listę argumentów i ich znaczenie w dokumentacji, nie mają absolutnie żadnych informacji poza niejasnym „wymaga pewnych argumentów”.

    Ten problem można prawdopodobnie rozwiązać ręcznie dokumentując metodę, zastępując automatycznie wygenerowaną dokumentację. Wymaga to dodatkowej pracy od implementatora metody, ale pamiętaj, że kod (i jego dokumentacja) jest odczytywany znacznie częściej niż jest napisany.

  • Jeśli kod jest ich dokumentacją, programiści, którzy używają metody z, **kwargspotrzebują dwóch dodatkowych kroków: muszą nie tylko spojrzeć na podpis metody, ale także na jej rzeczywistą implementację, aby znaleźć inną metodę, którą faktycznie wywołuje. Następnie muszą przejść na tę drugą metodę, aby w końcu znaleźć to, czego szukali.

    Nie wymaga to wiele wysiłku, ale wysiłek należy powtarzać raz po raz. Najgorsze jest to, że nie możesz im pomóc poprzez dodanie dokumentacji: jeśli skomentujesz swoją metodę, wymieniając rzeczywiste argumenty, istnieje duże ryzyko, że następna wersja biblioteki, którą wywoła metoda, będzie miała inne argumenty, a twoja dokumentacja będzie być przestarzałe, ponieważ nikt nie pamięta, że ​​należy go aktualizować.

Radzę polegać **kwargstylko na metodach o ograniczonym zakresie. Metody prywatne (i prywatne w kontekście Pythona, mam na myśli metody rozpoczynające się od _), które są używane w kilku miejscach w klasie, są na przykład dobrymi kandydatami. Z drugiej strony metody używane przez dziesiątki klas w całej bazie kodu są bardzo złymi kandydatami.

W końcu przepisanie argumentów metody, którą wywołujesz w pisanej metodzie, nie powinno wymagać zbyt wiele wysiłku. Mamy nadzieję, że większość metod nie przyjmuje więcej niż sześć do ośmiu argumentów, a jeśli tak, zadaj sobie pytanie, czy nie powinieneś refaktoryzować kodu. We wszystkich przypadkach:

  • Wyrażenie argumentów w twojej metodzie nie wymaga dużego wysiłku,

  • Możesz później chcieć zweryfikować argumenty (chociaż jeśli polegasz tylko na tym punkcie, aby wyjaśnić argumenty, naruszasz YAGNI).

Arseni Mourzenko
źródło
Naprawdę podoba mi się ta odpowiedź i uważam, że jest dobra. Niestety wiele naszego kodu ma wiele publicznych metod wykorzystujących ten wzorzec. Ale teraz mam argumenty, że powinniśmy to zmienić (i porzucić matplotlib, nigdy nie widziałem gorszego „interfejsu” ..)
Christian Sauer
3

Jeśli funkcja następnego poziomu ma __doc__, możesz po prostu skopiować __doc__ do nowej funkcji.

Na przykład:

def a(x):
    """This function takes one parameter, x, and does nothing with it!"""
    pass

def b(**kwargs):
    a(**kwargs)

b.__doc__=a.__doc__

Może to zostać zastosowane rekurencyjnie i może być zastosowane przez dekoratora (co może być przydatne, jeśli robisz to luzem). Można również manipulować ciągiem __doc__, aby dodać więcej na końcu. Oznacza to, że pokazane parametry nadal byłyby kwargami, ale przynajmniej w dokumentacji opisującej rzeczywiste parametry znajduje się pomoc.

AMADANON Inc.
źródło