web-dev-qa-db-fra.com

Python: éviter les avertissements pylint concernant trop d'arguments

Je veux reformer une grande fonction Python en une plus petite. Par exemple, considérons l'extrait de code suivant:

x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9

Bien sûr, ceci est un exemple trivial. En pratique, le code est plus complexe. Mon point est qu'il contient de nombreuses variables de portée locale qui devraient être transmises à la fonction extraite, ce qui pourrait ressembler à:

def mysum(x1, x2, x3, x4, x5, x6, x7, x8, x9):
    x = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
    return x

Le problème est que pylint déclencherait un avertissement concernant trop d’arguments ..__ Je pourrais éviter cet avertissement en procédant de la manière suivante:

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)

mais cette approche est moche pour moi, il faut écrire beaucoup de code, même redondant.

Y a-t-il une meilleure façon de le faire?

35
Anonymous

Tout d'abord, l'un des les épigrammes de Perlis :

"Si vous avez une procédure avec 10 paramètres , Vous en avez probablement manqué."

Certains des 10 arguments sont probablement liés. Regroupez-les dans un objet et transmettez-le à la place.

Donner l'exemple, car la question ne contient pas assez d'informations pour répondre directement:

class PersonInfo(object):
  def __init__(self, name, age, iq):
    self.name = name
    self.age = age
    self.iq = iq

Ensuite, votre fonction 10 arguments:

def f(x1, x2, name, x3, iq, x4, age, x5, x6, x7):
  ...

devient:

def f(personinfo, x1, x2, x3, x4, x5, x6, x7):
  ...

et l'appelant devient:

personinfo = PersonInfo(name, age, iq)
result = f(personinfo, x1, x2, x3, x4, x5, x6, x7)
81
user97370

Voulez-vous un meilleur moyen de faire passer les arguments ou juste un moyen d'empêcher pylint de vous donner du fil à retordre? Si ce dernier point, il me semble me rappeler que vous pourriez mettre fin à vos ennuis en plaçant pylint- contrôlant des commentaires dans votre code comme suit:

#pylint: disable-msg=R0913

ou:

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

en se rappelant de les rallumer dès que possible.

A mon avis, il n'y a rien de intrinsèquement mal à passer beaucoup d'arguments et de solutions préconisant de les emballer tous dans un argument conteneur, ne résolvent vraiment aucun problème, si ce n'est d'empêcher pylint de vous harceler :-).

Si vous devez passer vingt arguments, passez-les. Cela est peut-être nécessaire car votre fonction en fait trop et une refactorisation pourrait y contribuer, et vous devriez y réfléchir. Mais ce n’est pas une décision nous pouvons vraiment le faire si nous ne voyons pas ce qu'est le "vrai" code.

31
paxdiablo

Vous pouvez facilement modifier le nombre maximum d'arguments autorisés dans pylint. Ouvrez simplement votre fichier pylintrc (générez-le si vous n'en avez pas déjà un) et changez:

max-args = 5

à:

max-args = 6 # ou toute valeur qui vous convient 

De pylint's manual

Spécifier toutes les options appropriées pour votre installation et les normes de codage peut être fastidieux, il est donc possible de utilisez un fichier rc pour spécifier la valeur par défaut valeurs. Pylint cherche /etc/pylintrc et ~/.pylintrc. Le fichier --generate-rcfile L'option générera un commentaire Fichier de configuration selon le configuration actuelle en standard sortie et sortie. Vous pouvez mettre autre options avant celui-ci pour les utiliser dans la configuration, ou commencez par le valeurs par défaut et accordez manuellement le configuration.

20
Nadia Alramli

Vous pouvez essayer d'utiliser les arguments variables de Python feature:

def myfunction(*args):
    for x in args:
        # Do stuff with specific argument here
12
hbw

Vous pourriez peut-être transformer certains des arguments en variables membres. Si vous avez besoin de cela, un cours me semble une bonne idée. 

7
Brian Rasmussen

Simplifiez ou séparez la fonction afin qu'elle ne nécessite pas neuf arguments (ou ignorez pylint, mais utilisez des évitements comme ceux que vous proposez, annulez l'objectif d'un outil de lint).

EDIT: s'il s'agit d'une mesure temporaire, désactivez l'avertissement de la fonction en question à l'aide d'un commentaire, comme décrit ici: http://lists.logilab.org/pipermail/python-projects/2006-April/000664.html

Plus tard, vous pouvez grep pour tous les avertissements désactivés.

6
Dave

Commentaire sur la réponse de paxdiablo - car je n’ai pas assez de réputation pour commenter directement: - /

Je n'aime pas faire référence au numéro, le nom sybolique est beaucoup plus expressif et évite de devoir ajouter un commentaire qui pourrait devenir obsolète avec le temps.

Donc je préfère faire:

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

Et je vous recommande également de ne pas le laisser pendre là-dessus: il restera actif jusqu'à la fin du fichier ou s'il est désactivé, selon la première éventualité.

Alors mieux faire:

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

Je recommanderais également l'activation/désactivation d'un seul avertissement/erreur par ligne.

4
Igor Stoppa

Je suis tombé sur la même erreur lancinante, que je me suis rendue compte qu'il y a quelque chose à voir avec une fonctionnalité intéressante que PyCharm détecte automatiquement ... ajoutez simplement le décorateur @staticmethod et il supprimera automatiquement cette erreur lorsque la méthode est utilisée

0
Ants

Python a quelques outils de programmation fonctionnels Nice qui sont susceptibles de bien répondre à vos besoins. Départ Fonctions lambda et Carte . En outre, vous utilisez des dictés quand il semble que vous seriez beaucoup mieux servi avec des listes. Pour l'exemple simple que vous avez fourni, essayez cet idiome. Notez que la carte serait meilleure et plus rapide, mais qu'elle pourrait ne pas répondre à vos besoins:

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)

Vous avez mentionné avoir beaucoup de variables locales, mais franchement, si vous utilisez des listes (ou des nuplets), vous devez utiliser des listes et éliminer toutes ces variables locales à long terme.

0
easel