Pourquoi le point-virgule est-il autorisé dans cet extrait de code python?

166

Python ne garantit pas l'utilisation de points-virgules pour terminer les instructions. Alors pourquoi est-ce permis (ci-dessous)?

import pdb; pdb.set_trace()
canadadry
la source
1
Notez qu'un tel code est manifestement à des fins de débogage uniquement et serait vraisemblablement excisé avant qu'il ne soit "terminé". J'utilise cet extrait de code tel que vous l'avez pour pouvoir le déplacer facilement.
Nick T
Lol, je suis venu à cette question à partir du même site Web: realpython.com/python-debugging-pdb
mackycheese21

Réponses:

226

Python n'a pas besoin de points-virgules pour terminer les instructions. Les points virgules peuvent être utilisés pour délimiter des instructions si vous souhaitez mettre plusieurs instructions sur la même ligne.

Maintenant, pourquoi est-ce permis? C'est une décision de conception simple. Je ne pense pas que Python ait besoin de ce truc de point-virgule, mais quelqu'un a pensé que ce serait bien d'avoir et l'a ajouté au langage.

André Caron
la source
16
C'est utile pour des choses commetimeit a = 5; a*a
endolith
13
Cela semble utile pour les instructions exec, par exemple exec ('pour a dans [1,2,3]: imprimer a; imprimer a + 1')
Phil C
76
Je suis arrivé à Python avec un fond de C, Obj-C, Javascript, PHP. Je mets fréquemment un terminateur (inutile); à la fin d'une ligne. Mais heureusement, Python me pardonne
Paolo
36
Le point-virgule est très utile dans le shell django, ou dans le débogueur, vous pouvez donc écrire un petit programme sur une seule ligne et le répéter plus tard.
Bryce
5
@endolith Qu'est-ce que cela timeitsignifie? a = 2; a*aest inutile puisque avaut toujours 2; ça devrait êtrea = 2; a *= a
Nearoo
59

http://docs.python.org/reference/compound_stmts.html

Les instructions composées consistent en une ou plusieurs «clauses». Une clause se compose d'un en-tête et d'une «suite». Les en-têtes de clause d'une instruction composée particulière sont tous au même niveau d'indentation. Chaque en-tête de clause commence par un mot-clé d'identification unique et se termine par un signe deux-points. Une suite est un groupe d'instructions contrôlées par une clause. Une suite peut être une ou plusieurs instructions simples séparées par des points-virgules sur la même ligne que l'en-tête, après les deux points de l'en-tête, ou il peut s'agir d'une ou plusieurs instructions indentées sur les lignes suivantes . Seule cette dernière forme de suite peut contenir des instructions composées imbriquées; ce qui suit est illégal, principalement parce qu'il ne serait pas clair à quelle clause if une clause else suivante appartiendrait:

if test1: if test2: print x

Notez également que le point-virgule se lie plus étroitement que les deux-points dans ce contexte, de sorte que dans l'exemple suivant, toutes les instructions d'impression ou aucune ne sont exécutées:

if x < y < z: print x; print y; print z 

En résumé:

compound_stmt ::=  if_stmt
                   | while_stmt
                   | for_stmt
                   | try_stmt
                   | with_stmt
                   | funcdef
                   | classdef
                   | decorated
suite         ::=  stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT
statement     ::=  stmt_list NEWLINE | compound_stmt
stmt_list     ::=  simple_stmt (";" simple_stmt)* [";"]
chown
la source
4
Je ne savais pas que la priorité du point-virgule était inférieure à deux points après un si. Merci!
gaborous
3
@gaborous Je pense personnellement que votre commentaire est suffisamment ambigu pour me faire penser que vous voudriez dire le contraire. Donc, pour clarifier, je suggérerais plutôt aux autres lecteurs de s'en tenir à la phrase officielle: dans cet if cond: stmt1; stmt2; stmt3exemple, toutes ou aucune des déclarations sont exécutées. "
RayLuo
Oui, c'est ce que je voulais dire, si la priorité est moindre, alors le lexer ne peut pas quitter le bloc parent (deux-points) jusqu'à ce que toutes les instructions de point-virgule soient exécutées. Ce n'est vraiment pas une chose évidente.
gaborous
38

Python utilise le ;comme séparateur, pas comme terminateur. Vous pouvez également les utiliser à la fin d'une ligne, ce qui les fait ressembler à un terminateur d'instruction, mais cela n'est légal que parce que les instructions vides sont légales en Python - une ligne qui contient un point-virgule à la fin correspond à deux instructions, la seconde un blanc.

kindall
la source
28
Si vous mettez des points-virgules doubles à la fin (ou n'importe où), vous obtenez une SyntaxError. Il semble donc que les déclarations vierges ne soient pas entièrement légales.
Cucu
10
Il a probablement la même logique que les listes, les tuples, les dicts avec des virgules à la fin sont valides et les mêmes que leurs homologues coupés (par exemple [1,2,3] == [1,2,3,]) mais ils ne peuvent pas contenir de doubles virgules . Donc, fondamentalement, Python a un "suppresseur de blancs de fin". Ce qui ressort clairement de ceci:stmt_list ::= simple_stmt (";" simple_stmt)* [";"]
Cucu
@Cucu Vous avez raison. Vous ne pouvez pas non plus commencer une ligne par un point-virgule ou démarrer une liste d'expressions par une virgule. Il est donc plus précis de dire que les points-virgules et les virgules sont des séparateurs et des terminateurs facultatifs.
wjandrea le
29

Point-virgule dans l'interprète

Après avoir lu les réponses, il me manque encore un aspect important de l'utilisation des points-virgules, peut-être le seul où cela fait vraiment une différence ...

Lorsque vous travaillez dans un interpréteur REPL (le shell interactif Python, IDLE, ipython), la valeur de la dernière expression est affichée à l'écran et c'est généralement le comportement prévu.

Utiliser une expression pour les effets secondaires

Mais dans certains cas, vous souhaitez évaluer une expression uniquement pour ses effets secondaires, par exemple pour voir les résultats de votre simulation tracés par matplotlib.

Dans ce cas, vous ne voulez (probablement) pas voir l'écran plein de repr s des matplotlibobjets qui sont parfois renvoyés par un appel à une matplotlibfonction et, dans IPython au moins, l' une des possibilités que vous avez est d'ajouter un point - virgule à la trop instruction verbeuse , maintenant IPython voit la ligne d'entrée comme composée de deux expressions, l' matplotlibinvocation et une instruction nulle, de sorte que la valeur de l'expression composée est Noneet que rien ne soit imprimé à l'écran par l'interpréteur (l'autre possibilité étant l' affectation , comme dans _ = plot(...)mais je trouve ça un peu plus intrusif).

Remarque personnelle

À mon humble avis, l'utilisation du point-virgule pour supprimer la sortie non souhaitée dans l'interpréteur est devenue plus pertinente suite à l'introduction du cahier IPyton, qui permet de sauvegarder l'entrée et la sortie, y compris la sortie graphique, d'une session d'interprétation pour la documentation et la réutilisation éventuelle .

gboffi
la source
Je vois, merci pour le partage! Cela vient de résoudre exactement mon problème, où le point-virgule peut empêcher la repr par matplotlib dans un cahier
ipython
Ceci est une fonctionnalité uniquement IPython, et ce n'est pas une instruction null, juste une syntaxe spéciale.
wjandrea le
@wjandrea Vous avez raison, c'est juste ipython... J'ai modifié ma réponse pour refléter votre remarque.
gboffi
Cette réponse devrait être plus élevée, car je pense que c'est devenu le cas d'utilisation le plus courant (avec la diffusion du notebook Jupyter + le workflow IPython)
Josh Friedlander il y a
12

Comme tout le monde l'a noté, vous pouvez utiliser des points-virgules pour séparer les instructions. Vous n'avez et ce n'est pas le style habituel.

Quant à savoir pourquoi cela est utile, certaines personnes aiment mettre deux ou plusieurs déclarations courtes vraiment triviales sur une seule ligne (personnellement, je pense que cela transforme plusieurs lignes simples et faciles à parcourir en une ligne complexe et rend plus difficile de voir que c'est trivial) .

Mais c'est presque une exigence lorsque vous invoquez Python one liners à partir du shell en utilisant python -c '<some python code>'. Ici, vous ne pouvez pas utiliser l'indentation pour séparer les instructions, donc si votre one-liner est vraiment un two-liner, vous devrez utiliser un point-virgule. Et si vous souhaitez utiliser d'autres arguments dans votre one-liner, vous devrez importer syspour y accéder sys.argv, ce qui nécessite une importinstruction séparée . par exemple

python -c "import sys; print ' '.join(sorted(sys.argv[1:]))" 5 2 3 1 4
1 2 3 4 5
Ben
la source
2
Vous pouvez utiliser l'indentation et les retours à la ligne lorsque vous passez des commandes pythondans le shell: étalez simplement votre code cité sur plusieurs lignes ou utilisez un heredoc. Pourtant, cela échoue si vous voulez que ce soit un "one-liner". ;)
00dani
comprend des traits pour la réponse ferroviaire avec-c
n611x007
6

Je me rends compte que je suis biaisé en tant que vieux programmeur C, mais il y a des moments où les diverses conventions Python rendent les choses difficiles à suivre. Je trouve parfois la convention de retrait un peu ennuyeuse.

Parfois, il est très utile de savoir quand une instruction ou un bloc se termine. Le code C standard lira souvent quelque chose comme ceci:

for(i=0; i<100; i++) {
    do something here;
    do another thing here;
}

continue doing things;

où vous utilisez l'espace pour beaucoup de clarté - et il est facile de voir où la boucle se termine.

Python vous permet de terminer par un point-virgule (facultatif). Comme indiqué ci-dessus, cela ne signifie PAS qu'il y a une instruction à exécuter suivie d'une instruction «null». SO, par exemple,

print(x);
print(y);

Est le même que

print(x)
print(y)

Si vous pensez que le premier a une instruction nulle à la fin de chaque ligne, essayez - comme suggéré - de faire ceci:

print(x);;

Cela lancera une erreur de syntaxe.

Personnellement, je trouve le point-virgule pour rendre le code plus lisible lorsque vous avez beaucoup d'imbrication et de fonctions avec de nombreux arguments et / ou des arguments aux noms longs. Donc, à mes yeux, c'est beaucoup plus clair que d'autres choix:

if some_boolean_is_true:
    call_function(
        long_named_arg_1,
        long_named_arg_2,
        long_named_arg_3,
        long_named_arg_4
    );

puisque, pour moi, il vous permet de savoir que le dernier ')' termine un certain 'bloc' qui a parcouru plusieurs lignes.

Je pense personnellement qu'il y a beaucoup trop de lignes directrices de style PEP, d'IDE qui les appliquent, et la conviction qu'il n'y a «qu'une seule façon pythonique de faire les choses». Si vous croyez cela, regardez comment formater les nombres: à partir de maintenant, Python prend en charge quatre façons différentes de le faire.

Je suis sûr que je serai flambé par certains irréductibles, mais le compilateur / interpréteur ne se soucie pas de savoir si les arguments ont des noms longs ou courts, et - sauf pour la convention d'indentation en Python - ne se soucie pas des espaces. Le plus gros problème avec le code est de donner de la clarté à un autre humain (et même à vous-même après des mois de travail) pour comprendre ce qui se passe, où les choses commencent et finissent, etc.

eSurfsnake
la source
5

Une citation de " When Pythons Attack "

Ne terminez pas toutes vos instructions par un point-virgule. C'est techniquement légal de faire cela en Python, mais c'est totalement inutile à moins que vous ne placiez plus d'une instruction sur une seule ligne (par exemple, x = 1; y = 2; z = 3).

Communiste
la source
4
Pourquoi pas x,y,z = 1,2,3?
Anirban Nag 'tintinmj'
5
@ AnirbanNag'tintinmj 'Dans ce cas particulier, je crois que x, y, z = 1, 2, 3c'est plus lent car cela entraîne un aller-retour inutile de la construction d'un tuple, puis le désemble immédiatement. (Au fait, je ne pense pas vraiment que @communistpancake suggère le x=1; y=2; z=3modèle. Je pense qu'il / elle donne simplement un exemple de la façon dont le point-virgule est un séparateur plutôt qu'un terminateur.)
RayLuo
1
@AnirbanNag - parce que cela aurait été un exemple nul de ligne à plusieurs instructions.
cz
4

Plusieurs instructions sur une ligne peuvent inclure des points-virgules comme séparateurs. Par exemple: http://docs.python.org/reference/compound_stmts.html Dans votre cas, cela permet une insertion facile d'un point à percer dans le débogueur.

De plus, comme mentionné par Mark Lutz dans le livre Learning Python , il est techniquement légal (bien que inutile et ennuyeux) de terminer toutes vos déclarations par des points-virgules.

mandarg
la source
3

Python vous permet d'utiliser un point-virgule pour désigner la fin d'une instruction si vous incluez plus d'une instruction sur une ligne.

Godwin
la source
2

Les points-virgules peuvent être utilisés pour une ligne de deux commandes ou plus. Ils ne doivent pas être utilisés, mais ils ne sont pas limités.

Le point-virgule (;) autorise plusieurs instructions sur une seule ligne étant donné qu'aucune instruction ne démarre un nouveau bloc de code.

http://www.tutorialspoint.com/python/python_basic_syntax.htm

crâne vide
la source
2

Les points-virgules (comme les points, les virgules et les parenthèses) ont tendance à provoquer des guerres de religion. Pourtant, ils (ou un symbole similaire) sont utiles dans n'importe quel langage de programmation pour diverses raisons.

  • Pratique: la possibilité de mettre plusieurs commandes courtes qui appartiennent conceptuellement ensemble sur la même ligne. Un texte de programme qui ressemble à un serpent étroit a l'effet opposé de ce qui est prévu par les sauts de ligne et l'indentation, qui met en évidence la structure.

  • Conceptuel: séparation des soucis entre la syntaxe pure (dans ce cas, pour une séquence de commandes) et la présentation (ex: newline), autrefois appelée "jolie impression".

Observation: pour mettre en évidence la structure, l'indentation pourrait être augmentée / remplacée par des lignes verticales de manière évidente, servant de «règle visuelle» pour voir où une indentation commence et se termine. Des couleurs différentes (par exemple en suivant le code de couleur des résistances) peuvent compenser l'encombrement.

Raymond
la source
1

C'est autorisé car les auteurs ont décidé de l'autoriser: https://docs.python.org/2/reference/simple_stmts.html

Si vous vous demandez pourquoi les auteurs ont décidé de le faire, je suppose que c'est le cas parce que la demi-colonne est autorisée comme simple terminaison d'instruction au moins dans les langages suivants: C ++, C, C #, R, Matlab, Perl, ...

Il est donc plus rapide de passer à l'utilisation de Python pour les personnes ayant une formation dans une autre langue. Et il n'y a pas de perte de généralité dans une telle décision.

Bruziuz
la source
1

Le point-virgule (";") n'est nécessaire que pour la séparation des instructions dans un même bloc, par exemple si nous avons le code C suivant:

if(a>b)
{
largest=a;  //here largest and count are integer variables
count+=1;
}

Il peut être écrit en Python sous l'une des deux formes:

if a>b:   
    largest=a
    count=count+1

Ou

if a>b:    largest=a;count=count+1

Dans l'exemple ci-dessus, vous pouvez avoir n'importe quel nombre d'instructions dans un ifbloc et peuvent être séparés par ";" au lieu.

J'espère que rien n'est aussi simple que l'explication ci-dessus.

Mohd Asim
la source
0

En ajoutant aux vastes connaissances présentes ici,
c'est une réponse liée à la bibliothèque matplotlib

import numpy as np
import matplotlib as plt
%matplotlib notebook
linear_data = np.array([1, 2, 3, 4, 5, 6, 7, 8])
quadratic_data = linear_data**2
plt.figure()
xvals = range(len(linear_data))
plt.barh(xvals, linear_data, height = 0.3, color='b')
plt.barh(xvals, quadratic_data, height = 0.3, left=linear_data, color='r')

Si vous ne fournissez pas de point-virgule à la fin de la barre (barre horizontale), la sortie est un tracé + une adresse de fonction. Mais si vous utilisez des points-virgules à la fin des deux lignes de mesure, cela n'affiche que le tracé et supprime la sortie pour l'adresse de la fonction.

Quelque chose comme ça: comparaison

Farhan Khan
la source
3
Ceci est spécifique à IPython et ne s'applique pas au REPL Python standard.
wjandrea le
Je pense que c'est un exemple brillant où la façon dont les auteurs de langue pensaient introduire la simplicité, la puissance et l'uniformité n'a pas réussi à anticiper les problèmes comme celui-ci.
eSurfsnake