[Python] Хватит злоупотреблять *args и **kwargs в Python (перевод)

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
24-Дек-2020 00:31


Photo by Matthew Henry on UnsplashДа будет холивар! Использовать args/kwargs или не использовать, это показатель профессионализма или базовые знания, без которых должно быть стыдно? Часто листая github различных проектов натыкаешься на наличие данных аргументов в функциях просто потому что. И данная статья натолкнула на пообщаться на эту тему. Вообще, стараюсь не использовать неконтролируемое аргументирование на практике, но на сколько это вообще распространенный метод программирования? Делитесь в комментариях. И приятного чтения. В Интернете полно обучалок, которые научат вас использовать *args и **kwargs при определении функции в Python. Возможно, вы уже часами пытаетесь понять, как раскрыть их потенциал. Может быть, после всего этого исследования вы теперь чувствуете в них уверенность.Не надо!Мощные инструменты опасны. Вы могли облегчить свою жизнь, но запомните мои слова, они вскоре вернутся, чтобы преследовать вас.Но почему?Немного основПараметры в Python функции могут принимать два типа аргументов:
  • Позиционные аргументы, которые передаются позиционно.
  • Именованные аргументы, которые передаются с ключевыми словами.
def foo(start, end):
    print(start, end)
Например, foo ('Hi', end = 'Bye!') Передает позиционный аргумент "Hi" и именованный аргумент "Bye!", где ключевым словом выступает end для функции foo. Параметры функции предопределены; количество параметров, принимаемых в функции, фиксировано. Однако это не всегда так.*args позволяет передавать вашей функции произвольное количество позиционных аргументов. Звездочка * - параметр распаковки. Параметры упаковываются в виде итерируемого кортежа внутри функции.
def foo(*args):
    print(type(args))
    for arg in args:
        print(arg)
foo(1, 2, 'end')
# <class 'tuple'>
# 1
# 2
# end
С другой стороны, **kwargs позволяет передавать вашей функции произвольное количество аргументов с ключевыми словами. Поскольку у каждого именованного аргумента есть ключевое слово и значение, он сгруппирован как итерируемый словарь внутри функции.
def foo2(**kwargs):
    print(type(kwargs))
    for keyword, value in kwargs.items():
        print(f'{keyword}={value}')
foo2(a=1, b=2, z='end')
# <class 'dict'>
# a=1
# b=2
# z=end

Photo by Susan Holt Simpson on UnsplashПроблемаВ большинстве случаев вам действительно не нужны *args и **kwargs. Как часто вы не знаете, сколько аргументов должна получить предопределенная ВАМИ функция?Код гораздо сложнее отлаживать, если вы злоупотребляете в нем подобными решениями, потому что вы позволяете передавать произвольное количество аргументов функции, и функция может вести себя непредсказуемо.
Явное лучше, чем неявное. - Дзен Python
Когда всё-таки использовать аргументы?Если кратко: используйте их, когда они вам действительно нужны. Например, функция с множеством необязательных полей, и некоторые из них используются только в редких ситуациях. Скажем, функция строит график, и вы можете передавать различные необязательные аргументы, чтобы изменить его цвет, стиль, размер и т.д.Каждый раз, когда вы используете *args и/или **kwargs, убедитесь, что вы пишите к функциям ясную документацию, чтобы избежать путаницы.Есть один сценарий, в котором их использование может быть неизбежным. Если вы создаете оболочку для функции с неизвестными аргументами, вам нужно будет принять произвольное количество позиционных и именованных аргументов, а затем передать их функции.Например, декораторы в Python работают как оболочки, которые изменяют поведение кода, не изменяя сам код функции, тем самым расширяя дополнительные функции.
Photo by Alexander Schimmeck on UnsplashВ следующем примере мы создаем трассировку, которая выводит имя выполняемой функции в качестве проверки работоспособности. Декоратор применяется к функции с помощью @trace поверх функции, как показано ниже. Поскольку мы хотим применить этот декоратор к любым функциям с любым количеством аргументов, нам нужно использовать *args и **kwargs.
def trace(func):
    def print_in(*args, **kwargs):
        print('Executing function', func.__name__)
        return func(*args, **kwargs)
    return print_in
@trace
def calc(a,b):
    print(f'a+b is {a+b}, a-b is {a-b}.')
calc(1,2)
# Executing function calc
# a+b is 3, a-b is -1.
@trace
def add_all(*args):
    print(reduce(lambda a,b:a+b, args))
a = add_all(1,2,3,4,5)
# Executing function add_all
# 15
ВыводыПо возможности избегайте их.Обратите внимание, что args и kwargs так называются просто по соглашению. Вы можете называть их как хотите. Именно звездочки * и ** дают функциям ту самую мощь.
===========
Источник:
habr.com
===========

===========
Автор оригинала: Eden Au
===========
Похожие новости: Теги для поиска: #_python, #_python3, #_python
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Ноя 19:50
Часовой пояс: UTC + 5