** Кваргс - это антипаттерн?

16

У нас есть много кода в нашей внутренней кодовой базе, который вызывает наши библиотеки внутренне - у этих библиотек часто есть много аргументов (например, matplotlib), и наш код часто выполняет только определенную задачу и просто передает **kwargsследующую функцию, которая вызывается .

Например:

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

Хотя **kwargsмы не можем повторить все параметры в объявлении нашего метода, это также делает его чрезвычайно непрозрачным, какие аргументы являются допустимыми при вызове our_method- я должен знать, какой метод вызывается, чего я часто не хочу знать.

Что вы думаете об этом?

Кристиан Зауэр
источник

Ответы:

16

Как ваш код используется разработчиками? Другими словами, что именно они делают, чтобы определить, какие аргументы следует использовать и как?

  • Если они полагаются на документацию, автоматически сгенерированную из вашего кода, и генератор не имеет ни малейшего понятия, что с этим делать **kwargs, это действительно проблематично. Вместо того, чтобы найти список аргументов и их значение в документации, у них нет абсолютно никакой информации, кроме расплывчатого «требуется несколько аргументов».

    Эта проблема, вероятно, может быть решена путем документирования метода вручную, заменив документацию, созданную автоматически. Это требует дополнительной работы от разработчика метода, но помните, что код (и его документация) читаются гораздо чаще, чем пишутся.

  • Если код является их документацией, разработчикам, использующим метод, **kwargsнеобходимо выполнить два дополнительных шага: им нужно не только посмотреть на сигнатуру метода, но и на его фактическую реализацию, чтобы найти другой метод, который он фактически вызывает. Затем им нужно перейти к этому другому методу, чтобы, наконец, найти то, что они искали.

    Это не требует больших усилий, но, тем не менее, усилия должны повторяться снова и снова. Хуже всего то, что вы не можете помочь им, добавив документацию: если вы прокомментируете свой метод, перечисляя фактические аргументы, существует большой риск того, что в следующей версии библиотеки, которую вы вызываете из вашего метода, будут другие аргументы, и ваша документация будет быть устаревшим, так как никто не вспомнит, что это должно быть в курсе.

Я рекомендую полагаться **kwargsтолько на методы, которые имеют ограниченную область применения. Приватные методы (и частные в контексте Python, я имею в виду методы, начинающиеся с _), которые используются в нескольких местах в классе, являются хорошими кандидатами, например. С другой стороны, методы, которые используются десятками классов по всей кодовой базе, являются очень плохими кандидатами.

В конце концов, не нужно слишком много усилий переписывать аргументы метода, который вы вызываете, в методе, который вы пишете. Надеемся, что большинство методов не принимают более шести-восьми аргументов, и если они это сделают, спросите себя, не стоит ли проводить рефакторинг кода. В любом случае:

  • Выражение аргументов в вашем методе не требует больших усилий,

  • Позже вы можете захотеть проверить аргументы в любом случае (хотя, если вы полагаетесь только на этот аргумент, чтобы сделать аргументы явными, вы нарушаете YAGNI).

Арсений Мурзенко
источник
Мне очень нравится этот ответ, и я думаю, что он хороший. К сожалению, во многих наших кодах есть много открытых методов, использующих этот шаблон. Но теперь у меня есть аргументы в пользу того, что мы должны изменить его (и отбросить matplotlib, никогда не видевший более грубого «интерфейса» ..)
Кристиан Сауэр
3

Если функция следующего уровня имеет __doc__, то вы можете просто скопировать __doc__ в свою новую функцию.

Например:

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

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

b.__doc__=a.__doc__

Это может быть применено рекурсивно и может быть применено декоратором (что может быть полезно, если вы все равно делаете это массово). Строкой __doc__ можно также манипулировать, чтобы добавить больше в конец. Это означает, что показанные параметры все равно будут kwargs, но по крайней мере в справке есть документация, описывающая фактические параметры.

AMADANON Inc.
источник