Quelle est la règle de syntaxe pour avoir des virgules de fin dans les définitions de tuple?

119

Dans le cas d'un tuple d'élément unique, la virgule de fin est requise.

a = ('foo',)

Qu'en est-il d'un tuple avec plusieurs éléments? Il semble que, que la virgule de fin existe ou non, ils sont tous les deux valides. Est-ce correct? A mon avis, avoir une virgule à la fin est plus facile à éditer. Est-ce un mauvais style de codage?

a = ('foo1', 'foo2')
b = ('foo1', 'foo2',)
Stan
la source

Réponses:

73

Dans tous les cas, à l'exception du tuple vide, la virgule est la chose importante. Les parenthèses ne sont requises que lorsqu'elles sont requises pour d'autres raisons syntaxiques: pour distinguer un tuple d'un ensemble d'arguments de fonction, la priorité des opérateurs ou pour autoriser les sauts de ligne.

La virgule de fin pour les tuples, les listes ou les arguments de fonction est un bon style, en particulier lorsque vous avez une longue initialisation qui est divisée sur plusieurs lignes. Si vous incluez toujours une virgule à la fin, vous n'ajouterez pas une autre ligne à la fin en espérant ajouter un autre élément et en créant simplement une expression valide:

a = [
   "a",
   "b"
   "c"
]

En supposant que cela a commencé comme une liste de 2 éléments qui a ensuite été étendue, cela a mal tourné d'une manière peut-être pas immédiatement évidente. Incluez toujours la virgule de fin et évitez ce piège.

Duncan
la source
3
Pour les raisons exposées ci-dessus, laisser la virgule peut être avantageux. En revanche, adopter cette habitude peut entraîner des maux de tête si vous avez également affaire à JavaScript ou JSON ailleurs dans votre application, car certains navigateurs ne l'aiment pas là-bas.
Cito
7
Oui, mais vous ne devriez jamais construire JSON à la main, donc cela n'a pas d'importance, et pour Javascript, utilisez toujours jslint ou équivalent pour attraper ce genre d'erreur avant qu'il ne se rapproche d'un navigateur.
Duncan
100

Il est seulement nécessaire pour les tuples à élément unique de lever l'ambiguïté en définissant un tuple ou une expression entourée de parenthèses.

(1)  # the number 1 (the parentheses are wrapping the expression `1`)
(1,) # a 1-tuple holding a number 1

Pour plus d'un élément, ce n'est plus nécessaire car il est parfaitement clair qu'il s'agit d'un tuple. Cependant, la virgule de fin est autorisée pour faciliter leur définition en utilisant plusieurs lignes. Vous pouvez ajouter à la fin ou réorganiser les éléments sans casser la syntaxe, car vous avez omis une virgule par accident.

par exemple,

someBigTuple = (
                   0,
                   1,
                   2,
                   3,
                   4,
                   5,
                   6,
                   7,
                   8,
                   9,
                   10,
                   #...
                   10000000000,
               )

Notez que cela s'applique également à d'autres collections (par exemple, listes et dictionnaires) et pas seulement aux tuples.

Jeff Mercado
la source
5
+1 pour avoir souligné que cela est également valable pour d'autres éléments que les tuples. C'est tellement utile pour en avoir un key: value,par ligne, et ne pas prendre soin de la virgule lors de l'ajout de nouvelles choses.
Joël
46

Un autre avantage des virgules de fin est qu'elles rendent les différences plus jolies. Si vous avez commencé avec

a = [
    1,
    2,
    3
]

et l'a changé en

a = [
    1,
    2,
    3,
    4
]

Le diff ressemblerait à

 a = [
     1,
     2,
-    3
+    3,
+    4
 ]

Alors que si vous aviez commencé par une virgule, comme

a = [
    1,
    2,
    3,
]

Alors le diff serait juste

 a = [
     1,
     2,
     3,
+    4,
 ]
asmeureur
la source
C'est vraiment plus un commentaire qu'une réponse à la question originale, mais j'aime vraiment l'argument ajouté en faveur des virgules.
Mad Physicist
13

C'est facultatif: voir le wiki Python .

Résumé: les tuples à un seul élément nécessitent une virgule à la fin , mais c'est facultatif pour les tuples à plusieurs éléments.

Dave Everitt
la source
8

Pensez également à la situation dans laquelle vous souhaitez:

>>> (('x','y'))*4                         # same as ('x','y')*4
('x', 'y', 'x', 'y', 'x', 'y', 'x', 'y')
#Expected = (('x', 'y'), ('x', 'y'), ('x', 'y'), ('x', 'y'))

Donc, dans ce cas, les parenthèses extérieures ne sont rien de plus que des parenthèses de regroupement. Pour les rendre tuple, vous devez ajouter une virgule de fin. c'est à dire

>>> (('x','y'),)*4 
(('x', 'y'), ('x', 'y'), ('x', 'y'), ('x', 'y'))
MaPy
la source
6

La virgule de fin est requise pour les tuples à un élément uniquement. Avoir une virgule de fin pour les tuples plus grands est une question de style et n'est pas obligatoire. Son plus grand avantage est la netteté des différences sur les fichiers avec de grands tuples multilignes qui sont souvent modifiés (par exemple des tuples de configuration).

Adam Zalcman
la source
6

C'est une réponse simple.

a = ("s") est une chaîne

et

a = ("s",) est un tuple avec un élément.

Python a besoin d'une virgule supplémentaire dans le cas d'un tuple d'élément pour différencier chaîne et tuple.

Par exemple, essayez ceci sur la console python:

a = ("s")

a = a + (1,2,3)

Traceback (dernier appel le plus récent):

Fichier stdin, ligne 1, dans le module

TypeError: impossible de concaténer les objets 'str' et 'tuple'

Rajni Kant
la source
4

Une autre raison pour laquelle cela existe est que cela facilite la génération de code et les __repr__fonctions. Par exemple, si vous avez un objet construit comme obj(arg1, arg2, ..., argn), alors vous pouvez simplement écrire obj.__repr__comme

def __repr__(self):
    l = ['obj(']
    for arg in obj.args: # Suppose obj.args == (arg1, arg2, ..., argn)
        l.append(repr(arg))
        l.append(', ')
    l.append(')')
    return ''.join(l)

Si une virgule de fin n'était pas autorisée, vous devrez mettre en cas particulier le dernier argument. En fait, vous pouvez écrire ce qui précède sur une ligne en utilisant une compréhension de liste (je l'ai écrit plus longtemps pour le rendre plus facile à lire). Ce ne serait pas si facile de faire cela si vous deviez caser le dernier trimestre.

asmeureur
la source
2
Il n'y aurait pas besoin de cas particulier du dernier argument, on pourrait simplement utiliser join dans ce cas: def __repr__(self): 'obj(' + ', '.join([repr(arg) for arg in obj.args]) + ')'.
Suzanne Dupéron
Cela aide également à la génération de code, même à partir d'outils qui ne sont pas écrits en Python et qui n'ont pas de fonctions intéressantes comme join.
asmeurer le
2

PEP 8 - Guide de style pour le code Python - Quand utiliser des virgules de fin

Les virgules de fin sont généralement facultatives, sauf qu'elles sont obligatoires lors de la création d'un tuple d'un élément (et en Python 2, elles ont une sémantique pour l'instruction d'impression). Pour plus de clarté, il est recommandé d'entourer ce dernier de parenthèses (techniquement redondantes).

Oui:

FILES = ('setup.cfg',)

OK, mais déroutant:

FILES = 'setup.cfg',

Lorsque les virgules de fin sont redondantes, elles sont souvent utiles lorsqu'un système de contrôle de version est utilisé, lorsqu'une liste de valeurs, d'arguments ou d'éléments importés est censée être étendue au fil du temps. Le modèle consiste à mettre chaque valeur (etc.) sur une ligne par elle-même, en ajoutant toujours une virgule à la fin, et à ajouter la parenthèse / crochet / accolade ferme sur la ligne suivante. Cependant, cela n'a pas de sens d'avoir une virgule de fin sur la même ligne que le délimiteur de fermeture (sauf dans le cas ci-dessus des tuples singleton).

Oui:

FILES = [
    'setup.cfg',
    'tox.ini',
    ]
initialize(FILES,
           error=True,
           )

Non:

FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)
Match rapide
la source
-5

Le style de codage est à votre goût.Si vous pensez que la norme de codage est importante, il existe un PEP-8 qui peut vous guider.

Que pensez-vous du résultat de l'expression suivante?

x = (3)
x = (3+2)
x = 2*(3+2)

Oui, x n'est qu'un nombre.

Melug
la source
1
c'est une mauvaise manière d'expliquer votre ligne de pensée. Explicite vaut mieux qu'implicite.
Guilherme David da Costa