Python: избегать предупреждений pylint о слишком многих аргументах
Я хочу реорганизовать большую функцию Python на более мелкие. Например, рассмотрим следующий фрагмент кода:
x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
Конечно, это тривиальный пример. На практике код более сложный. Я хочу сказать, что он содержит много переменных локальной области видимости, которые должны быть переданы в извлеченную функцию, которая может выглядеть так:
def mysum(x1, x2, x3, x4, x5, x6, x7, x8, x9):
x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
return x
Проблема заключается в том, что pylint вызовет предупреждение о слишком большом количестве аргументов.
Я мог бы избежать предупреждения, сделав что-то вроде:
def mysum(d):
x1 = d['x1']
x2 = d['x2']
...
x9 = d['x9']
x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
return x
def mybigfunction():
...
d = {}
d['x1'] = x1
...
d['x9'] = x9
x = mysum(d)
но этот подход не уродливый для меня, он требует написания большого количества кода, который даже лишний.
Есть ли лучший способ сделать это?
Ответы
Ответ 1
Во-первых, один из Perlis epigrams:
"Если у вас есть процедура с 10 параметры, вы, вероятно, пропустили некоторые."
Некоторые из 10 аргументов предположительно связаны между собой. Группируйте их в объект и передайте это вместо.
Приведите пример вверх, потому что в ответе на него недостаточно информации:
class PersonInfo(object):
def __init__(self, name, age, iq):
self.name = name
self.age = age
self.iq = iq
Затем ваша 10-функция аргумента:
def f(x1, x2, name, x3, iq, x4, age, x5, x6, x7):
...
становится:
def f(personinfo, x1, x2, x3, x4, x5, x6, x7):
...
и вызывающий абонент изменит на:
personinfo = PersonInfo(name, age, iq)
result = f(personinfo, x1, x2, x3, x4, x5, x6, x7)
Ответ 2
Вам нужен лучший способ передать аргументы или просто остановить pylint
от трудностей? Если последнее, я, кажется, вспоминаю, что вы можете остановить ворчание, добавив pylint
-controlling комментарии в свой код в соответствии с строками:
#pylint: disable-msg=R0913
или
#pylint: disable-msg=too-many-arguments
помня о том, чтобы вернуть их как можно скорее.
По-моему, нет ничего неправильного в передаче большого количества аргументов и решений, защищающих их включение в какой-либо контейнерный аргумент, на самом деле не решает никаких проблем, кроме как остановить pylint
от nagging you: -).
Если вам нужно передать двадцать аргументов, передайте их. Возможно, это необходимо, потому что ваша функция делает слишком много, и рефакторинг может помочь там и что-то, на что вы должны смотреть. Но это не решение, которое мы действительно можем сделать, если не увидим, что такое "настоящий" код.
Ответ 3
Вы можете легко изменить максимально допустимое количество аргументов в pylint. Просто откройте файл pylintrc (сгенерируйте его, если у вас его еще нет) и измените:
макс-арг = 5
чтобы:
max-args = 6 # или любое подходящее вам значение
Из руководства Пилинта
Указание всех параметров, подходящих для ваших настроек и стандартов кодирования, может быть утомительным, поэтому можно использовать файл rc для указания значений по умолчанию. Pylint ищет /etc/pylintrc и ~/.pylintrc. Опция --generate-rcfile создаст закомментированный файл конфигурации в соответствии с текущей конфигурацией стандартного вывода и выхода. Вы можете поставить другие опции перед этим, чтобы использовать их в конфигурации, или начать со значений по умолчанию и вручную настроить конфигурацию.
Ответ 4
Вы можете попробовать использовать аргументы переменной python:
def myfunction(*args):
for x in args:
# Do stuff with specific argument here
Ответ 5
Возможно, вы могли бы превратить некоторые из аргументов в переменные-члены. Если вам нужно такое состояние, класс звучит как хорошая идея для меня.
Ответ 6
Упростите или разбейте функцию так, чтобы она не требовала девяти аргументов (или игнорировала pylint, но уклонилась, как те, которые вы предлагаете, чтобы победить цель инструмента линта).
EDIT: если это временная мера, отключите предупреждение для конкретной функции, используя комментарий, как описано здесь: http://lists.logilab.org/pipermail/python-projects/2006-April/000664.html
Позже вы можете grep для всех отключенных предупреждений.
Ответ 7
Мне не нравится ссылаться на число, это синонимы гораздо более выразительны и избегают добавления комментариев, которые со временем могут устареть.
Так что я бы лучше сделал:
#pylint: disable-msg=too-many-arguments
И я бы также рекомендовал не оставлять его там болтаться: он будет оставаться активным до тех пор, пока файл не закончится или не будет отключен, в зависимости от того, что наступит раньше.
Так лучше делать
#pylint: disable-msg=too-many-arguments
code_which_would_trigger_the_msg
#pylint: enable-msg=too-many-arguments
Я также рекомендовал бы включить/отключить одно предупреждение/ошибку на строку.
Ответ 8
У Python есть хорошие инструменты для функционального программирования, которые, вероятно, будут хорошо соответствовать вашим потребностям. Проверьте лямбда-функции и map. Кроме того, вы используете dicts, когда кажется, что вам будет гораздо лучше подавать списки. Для простого примера, который вы предоставили, попробуйте эту идиому. Обратите внимание, что карта будет лучше и быстрее, но может не соответствовать вашим потребностям:
def mysum(d):
s = 0
for x in d:
s += x
return s
def mybigfunction():
d = (x1, x2, x3, x4, x5, x6, x7, x8, x9)
return mysum(d)
Вы упомянули о наличии множества локальных переменных, но, откровенно говоря, если вы имеете дело со списками (или кортежами), вы должны использовать списки и учитывать все эти локальные переменные в долгосрочной перспективе.
Ответ 9
Я столкнулся с той же самой ноющей ошибкой, которая, как я понял, как-то связана с классной функцией, которую PyCharm автоматически обнаруживает... просто добавьте декоратор @staticmethod, и он автоматически удалит эту ошибку при использовании метода