Python: избегать предупреждений Pylint о слишком большом количестве аргументов - PullRequest
39 голосов
/ 03 мая 2009

Я хочу преобразовать большую функцию 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)

но такой подход мне некрасив, требует написания большого количества кода, который даже избыточен.

Есть ли лучший способ сделать это?

Ответы [ 9 ]

86 голосов
/ 03 мая 2009

Сначала один из эпиграмм Перлиса :

"Если у вас есть процедура с 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)
35 голосов
/ 03 мая 2009

Хотите ли вы лучший способ передачи аргументов или просто способ не дать pylint доставить вам неприятности? Если последнее, я, кажется, вспоминаю, что вы могли бы прекратить нытье, поместив в свой код комментарии pylint, которые выглядят так:

#pylint: disable-msg=R0913

или

#pylint: disable-msg=too-many-arguments

не забывая включать их как можно скорее.

По моему мнению, нет ничего по своей сути неправильно с передачей большого количества аргументов и решений, призывающих заключать их все в какой-то контейнерный аргумент, на самом деле не решает никаких проблем, кроме остановки pylint от ворчания Вы: -).

Если вам нужно передать двадцать аргументов, передайте их. Может случиться так, что это требуется, потому что ваша функция делает слишком много, и рефакторинг может помочь в этом, и это то, на что вам следует обратить внимание. Но это не решение , которое мы можем действительно принять, если не увидим, что такое «настоящий» код.

21 голосов
/ 03 мая 2009

Вы можете легко изменить максимально допустимое количество аргументов в pylint. Просто откройте файл pylintrc (сгенерируйте его, если у вас его еще нет) и измените:

макс-арг = 5

до:

max-args = 6 # или любое подходящее вам значение

Из руководства Пилинта

указание всех подходящих вариантов для вашей установки и стандартов кодирования может быть утомительным, так что можно используйте файл rc, чтобы указать значение по умолчанию ценности. Pylint ищет / etc / pylintrc и ~ / .pylintrc. --Generate-rcfile опция сгенерирует комментарий файл конфигурации в соответствии с текущая конфигурация по стандарту выход и выход. Вы можете поставить другие варианты до этого, чтобы использовать их в конфигурации, или начните с значения по умолчанию и ручная настройка конфигурации.

12 голосов
/ 03 мая 2009

Вы можете попробовать использовать переменные аргументы Python функция:

def myfunction(*args):
    for x in args:
        # Do stuff with specific argument here
7 голосов
/ 03 мая 2009

Возможно, вы могли бы превратить некоторые аргументы в переменные-члены. Если вам нужно так много заявить, класс звучит для меня как хорошая идея.

6 голосов
/ 03 мая 2009

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

РЕДАКТИРОВАТЬ: если это временная мера, отключите предупреждение для конкретной функции, используя комментарий, как описано здесь: http://lists.logilab.org/pipermail/python-projects/2006-April/000664.html

Позже вы можете выполнить grep для всех отключенных предупреждений.

4 голосов
/ 06 ноября 2014

Мне не нравится ссылаться на число, символическое имя гораздо более выразительно и избегать добавления комментария, который со временем может устареть.

Так что я бы лучше сделал:

#pylint: disable-msg=too-many-arguments

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

Так лучше делать:

#pylint: disable-msg=too-many-arguments
code_which_would_trigger_the_msg
#pylint: enable-msg=too-many-arguments    

Я бы также рекомендовал включить / отключить одно предупреждение / ошибку на строку.

0 голосов
/ 05 января 2019

Я столкнулся с той же самой ноющей ошибкой, которая, как я понял, как-то связана с классной функцией, которую PyCharm автоматически обнаруживает ... просто добавьте декоратор @staticmethod, и он автоматически удалит эту ошибку при использовании метода

0 голосов
/ 03 мая 2009

В 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)

Вы упомянули о наличии множества локальных переменных, но, честно говоря, если вы имеете дело со списками (или кортежами), вы должны использовать списки и выделять все эти локальные переменные в долгосрочной перспективе.

...