2017-06-22 3 views
5

En Python, en laissant une virgule finale comme celui-ci est, bien sûr, pas SyntaxError:virgule finale Unintentional qui crée un tuple

In [1]: x = 1 , 

In [2]: x 
Out[2]: (1,) 

In [3]: type(x) 
Out[3]: tuple 

Mais, en même temps, si la virgule finale a été mis accidentellement, il peut être difficile d'attraper ce genre de "problème", en particulier pour les nouveaux arrivants Python.

Je pense si nous pouvons attraper ce genre de début « problème », statiquement, avec l'aide de PyCharm smart fonctions de contrôle de la qualité du code; mypy, pylint ou flake8 des outils d'analyse de code statique.

Ou, une autre idée serait de restreindre/mettre en surbrillance en créant implicitement un nombre d'éléments sans parenthèse. C'est possible?

+0

@onlynone BTW, je ne suis pas sûr de ce que vous vouliez dire par la première question/déclaration. Dois-je en mettre un de plus "Est-ce possible?" à la première partie de la question? Je pense que c'est clair ce que je voulais dire, mais laissez-moi savoir s'il y a quelque chose qui peut être amélioré pour rendre la question plus propre. Merci. – alecxe

+1

Je suppose que c'est bien. C'était juste bizarrement formulé: "est-ce possible (pour détecter ce problème avec l'analyse de code statique)" est un peu évident "oui!" - C'est précisément ce que font les outils d'analyse de code statique. Et il s'avère que l'un des plus populaires pour python, et celui que vous mentionnez vous-même, fait exactement ce que vous voulez. L'autre interprétation, "est-ce possible (restreindre la création de tuples d'item sans parens)", semblerait être un "non" évident puisque c'est comme ça que fonctionne python. – onlynone

+1

PEP8 est inhabituellement vague en décrivant cette utilisation de virgules flottantes comme "OK, mais déroutant:" Je m'attendrais à des conseils plus fiables https://www.python.org/dev/peps/pep-0008/#when-to-use- trailing-virgules –

Répondre

11

pylint déjà détecté cela comme un problème (as of version 1.7).

Par exemple, voici mon tuple.py:

"""Module docstring to satisfy pylint""" 

def main(): 
    """The main function""" 
    thing = 1, 
    print(type(thing)) 

if __name__ == "__main__": 
    main() 
$ pylint tuple.py 
No config file found, using default configuration 
************* Module tuple 
R: 5, 0: Disallow trailing comma tuple (trailing-comma-tuple) 

------------------------------------------------------------------ 
Your code has been rated at 8.00/10 (previous run: 8.00/10, +0.00) 

$ pylint --help-msg trailing-comma-tuple 
No config file found, using default configuration 
:trailing-comma-tuple (R1707): *Disallow trailing comma tuple* 
    In Python, a tuple is actually created by the comma symbol, not by the 
    parentheses. Unfortunately, one can actually create a tuple by misplacing a 
    trailing comma, which can lead to potential weird bugs in your code. You 
    should always use parentheses explicitly for creating a tuple. This message 
    belongs to the refactoring checker. It can't be emitted when using Python < 
    3.0. 
0

Ce comportement n'est pas inattendu car l'opérateur de ligne multiple est ,, et non (). Le rôle de la parenthèse ici est le même que dans les expressions arithmétiques. Vous ne pouvez donc pas restreindre une telle création dans un interpréteur Python, sinon ce serait une autre langue. Je suis d'accord qu'une virgule traînante est parfois involontaire. Les outils de peluches tels que pylint sont souvent capables d'intercepter de telles erreurs au moyen d'une inférence de type générale (c'est-à-dire qu'ils voient que vous essayez d'ajouter un tuple à un nombre). (Notez également que les virgules sont parfois utiles et moins involontaires, par exemple dans the_only_elem, = our_list.) Une autre option consiste à écrire votre propre linter simple qui vérifie quelque chose comme line.rstrip().endswith(',') and '=' in line (la deuxième vérification consiste à autoriser une déclaration de liste multiligne dans une certaine mesure).

+0

votre vérificateur linter donnerait beaucoup de faux positifs (au moins dans mon code): 'data = func (param1, \ n param2 ...)' – MariusSiuram

+0

@MariusSiuram Il n'y a pas mon "vérificateur de linter" dans la réponse, juste un illustration. J'ai mentionné que ce n'est pas parfait. –