Warum ist Semikolon in diesem Python-Snippet zulässig?

166

Python garantiert nicht die Verwendung von Semikolons zum Beenden von Anweisungen. Warum ist das (unten) erlaubt?

import pdb; pdb.set_trace()
Kanada trocken
quelle
1
Beachten Sie, dass dieser Code nur zu Debugging-Zwecken dient und vermutlich entfernt wird, bevor er "fertig" ist. Ich benutze dieses Snippet so, wie Sie es haben, damit ich es leicht bewegen kann.
Nick T
Lol Ich kam zu dieser Frage von der gleichen Website: realpython.com/python-debugging-pdb
mackycheese21

Antworten:

225

Python nicht erforderlich Semikolons Aussagen zu beenden. Semikolons können zum Abgrenzen von Anweisungen verwendet werden, wenn Sie mehrere Anweisungen in dieselbe Zeile setzen möchten.

Nun, warum ist das erlaubt? Es ist eine einfache Designentscheidung. Ich glaube nicht, dass Python dieses Semikolon-Ding braucht, aber jemand dachte, es wäre schön, es zu haben, und fügte es der Sprache hinzu.

André Caron
quelle
16
Es ist nützlich für Dinge wietimeit a = 5; a*a
Endolith
13
Es scheint nützlich für exec-Anweisungen zu sein, zB exec ('für a in [1,2,3]: print a; print a + 1')
Phil C
75
Ich bin mit einem Hintergrund von C, Obj-C, Javascript, PHP zu Python gekommen. Ich setze häufig einen (nutzlosen) Terminator; am Ende einer Zeile. Aber zum Glück vergibt Python mir
Paolo
36
Das Semikolon ist in der Django-Shell oder im Debugger sehr nützlich, sodass Sie ein kleines Programm in eine einzelne Zeile schreiben und später wiederholen können.
Bryce
5
@endolith Was bedeutet timeitdas? a = 2; a*aist nutzlos, da aes immer noch 2 ist; es müsste seina = 2; a *= a
Nearoo
58

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

Zusammengesetzte Aussagen bestehen aus einer oder mehreren 'Klauseln'. Eine Klausel besteht aus einem Header und einer 'Suite'. Die Klauselüberschriften einer bestimmten zusammengesetzten Anweisung befinden sich alle auf derselben Einrückungsstufe. Jeder Klauselheader beginnt mit einem eindeutig identifizierenden Schlüsselwort und endet mit einem Doppelpunkt. Eine Suite ist eine Gruppe von Anweisungen, die von einer Klausel gesteuert werden. Eine Suite kann eine oder mehrere durch Semikolons getrennte einfache Anweisungen in derselben Zeile wie die Kopfzeile sein, die dem Doppelpunkt der Kopfzeile folgen, oder eine oder mehrere eingerückte Anweisungen in nachfolgenden Zeilen . Nur die letztere Form der Suite kann verschachtelte zusammengesetzte Anweisungen enthalten. Folgendes ist illegal, vor allem, weil nicht klar wäre, zu welcher if-Klausel eine folgende else-Klausel gehören würde:

if test1: if test2: print x

Beachten Sie auch, dass das Semikolon in diesem Zusammenhang enger als der Doppelpunkt ist, sodass im folgenden Beispiel entweder alle oder keine der print-Anweisungen ausgeführt werden:

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

Zusammenfassend:

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
quelle
4
Wusste nicht, dass das Semikolon nach einem Wenn weniger als der Doppelpunkt ist. Vielen Dank!
gaborous
3
@gaborous Ich persönlich empfinde Ihren Kommentar als mehrdeutig genug, um mich glauben zu lassen, Sie würden es anders meinen. Um dies zu verdeutlichen, würde ich anderen Lesern eher empfehlen, sich an den offiziellen Satz zu halten: In diesem if cond: stmt1; stmt2; stmt3Beispiel werden entweder alle oder keine der Anweisungen ausgeführt. "
RayLuo
Ja, das habe ich gemeint. Wenn die Priorität geringer ist, kann der Lexer den übergeordneten Block (Doppelpunkt) nicht verlassen, bis alle Semikolonanweisungen ausgeführt wurden. Das ist wirklich keine offensichtliche Sache.
gaborous
38

Python verwendet das ;als Trennzeichen, nicht als Terminator. Sie können sie auch am Ende einer Zeile verwenden, wodurch sie wie ein Anweisungsabschluss aussehen. Dies ist jedoch nur zulässig, da leere Anweisungen in Python zulässig sind. Eine Zeile, die am Ende ein Semikolon enthält, besteht aus zwei Anweisungen, der zweiten ein Leerzeichen.

irgendwie
quelle
28
Wenn Sie am Ende (oder irgendwo) doppelte Semikolons einfügen, erhalten Sie einen SyntaxError. Es scheint also, dass leere Aussagen nicht ganz legal sind.
Cucu
10
Wahrscheinlich hat es die gleiche Logik wie Listen, Tupel, Diktate mit nachgestellten Kommas und die gleichen wie ihre zugeschnittenen Gegenstücke (z. B. [1,2,3] == [1,2,3,]), aber sie dürfen keine Doppelkommas enthalten . Grundsätzlich hat Python einen "Trailing Blank Remover". Was übrigens daraus hervorgeht:stmt_list ::= simple_stmt (";" simple_stmt)* [";"]
Cucu
@Cucu Du hast recht. Sie können eine Zeile auch nicht mit einem Semikolon oder eine Ausdrucksliste mit einem Komma beginnen. Es ist also genauer zu sagen, dass Semikolons und Kommas Trennzeichen und optionale Abschlusszeichen sind.
Wjandrea
28

Semikolon im Dolmetscher

Nachdem ich die Antworten gelesen habe, vermisse ich immer noch einen wichtigen Aspekt bei der Verwendung von Semikolons, möglicherweise den einzigen, bei dem es wirklich einen Unterschied macht ...

Wenn Sie in einem Interpreter REPL (der interaktiven Python-Shell, IDLE, ipython) arbeiten, wird der Wert des letzten Ausdrucks auf dem Bildschirm gedruckt, und normalerweise ist dies das beabsichtigte Verhalten.

Verwenden eines Ausdrucks für Nebenwirkungen

In einigen Fällen möchten Sie einen Ausdruck jedoch nur auf seine Nebenwirkungen untersuchen, z. B. um die Ergebnisse Ihrer Simulation von zu zeichnen matplotlib .

In diesen Fällen möchten Sie (wahrscheinlich) nicht den Bildschirm mit reprs von matplotlibObjekten sehen, die manchmal durch einen Aufruf einer matplotlibFunktion zurückgegeben werden, und zumindest in IPython besteht eine der Möglichkeiten darin, ein Semikolon an das Overly anzuhängen Ausführliche Anweisung, jetzt sieht IPython die Eingabezeile als aus zwei Ausdrücken zusammengesetzt, dem matplotlibAufruf und einer Null-Anweisung, so dass der Wert des zusammengesetzten Ausdrucks ist Noneund nichts vom Interpreter auf dem Bildschirm gedruckt wird (die andere Möglichkeit ist die Zuweisung , wie in _ = plot(...)aber ich finde das etwas aufdringlicher).

Persönliche Bemerkung

Meiner Meinung nach ist die Verwendung des Semikolons zur Unterdrückung unerwünschter Ausgaben im Interpreter nach der Einführung des IPyton-Notizbuchs relevanter geworden, mit dem die Eingabe und die Ausgabe, einschließlich der grafischen Ausgabe, einer Interpretersitzung zur Dokumentation und eventuellen Wiederverwendung gespeichert werden können .

gboffi
quelle
Ich verstehe, danke fürs Teilen! Dies hat genau mein Problem gelöst, bei dem Semikolon die Repräsentation durch Matplotlib im Ipython-Notizbuch verhindern kann
Napitupulu Jon
Dies ist eine reine IPython-Funktion und keine Null-Anweisung, sondern nur eine spezielle Syntax.
Wjandrea
@wjandrea Du hast Recht, es ist nur ipython... Ich habe meine Antwort bearbeitet, um deine Bemerkung widerzuspiegeln.
Gboffi
12

Wie alle anderen darauf hingewiesen hat, Sie können Semikolons trennen Anweisungen verwenden. Sie müssen nicht haben , und es ist nicht die übliche Art.

Was den Grund angeht, warum dies nützlich ist, möchten manche Leute zwei oder mehr wirklich triviale kurze Aussagen in eine einzelne Zeile setzen (ich persönlich denke, dies verwandelt mehrere triviale, leicht zu überfliegende Zeilen in eine komplex aussehende Zeile und macht es schwieriger zu erkennen, dass sie trivial ist). .

Aber es ist fast eine Voraussetzung, wenn Sie Python One-Liner aus der Shell mit aufrufen python -c '<some python code>'. Hier können Sie Einrückungen nicht verwenden, um Anweisungen zu trennen. Wenn Ihr Einzeiler also wirklich ein Zweiliner ist, müssen Sie ein Semikolon verwenden. Und wenn Sie andere Argumente in Ihrem Einzeiler verwenden möchten, müssen Sie importieren sys, um zu gelangen sys.argv, was eine separate importAnweisung erfordert . z.B

python -c "import sys; print ' '.join(sorted(sys.argv[1:]))" 5 2 3 1 4
1 2 3 4 5
Ben
quelle
2
Sie können Einrückungen und Zeilenumbrüche verwenden, wenn Sie Befehle pythonin der Shell weitergeben: Spannen Sie Ihren zitierten Code einfach über mehrere Zeilen oder verwenden Sie einen Heredoc. Dies schlägt jedoch fehl, wenn Sie möchten, dass es sich um einen "Einzeiler" handelt. ;)
00dani
enthält Merkmale für die Schienenantwort mit-c
n611x007
6

Mir ist klar, dass ich als alter C-Programmierer voreingenommen bin, aber es gibt Zeiten, in denen die verschiedenen Python-Konventionen es schwierig machen, den Dingen zu folgen. Ich finde die Einrückungskonvention manchmal etwas ärgerlich.

Manchmal ist es sehr nützlich, klar zu machen, wann eine Anweisung oder ein Block endet. Standard-C-Code lautet häufig wie folgt:

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

continue doing things;

wo Sie das Leerzeichen für viel Klarheit verwenden - und es ist leicht zu erkennen, wo die Schleife endet.

Mit Python können Sie mit einem (optionalen) Semikolon beenden. Wie oben erwähnt, bedeutet dies NICHT, dass eine Anweisung ausgeführt werden muss, gefolgt von einer Nullanweisung. SO zum Beispiel

print(x);
print(y);

Ist das gleiche wie

print(x)
print(y)

Wenn Sie der Meinung sind, dass die erste am Ende jeder Zeile eine Null-Anweisung enthält, versuchen Sie - wie vorgeschlagen - Folgendes:

print(x);;

Es wird ein Syntaxfehler ausgegeben.

Persönlich finde ich das Semikolon, um Code lesbarer zu machen, wenn Sie viele Verschachtelungen und Funktionen mit vielen Argumenten und / oder lang benannten Argumenten haben. Für mich ist dies viel klarer als andere Entscheidungen:

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

da es mich wissen lässt, dass das letzte ')' einen 'Block' beendet, der über viele Zeilen lief.

Ich persönlich denke, es gibt viel zu viele Richtlinien im PEP-Stil, IDEs, die sie durchsetzen, und die Überzeugung, dass es „nur einen pythonischen Weg gibt, Dinge zu tun“. Wenn Sie letzteres glauben, schauen Sie sich an, wie Sie Zahlen formatieren: Ab sofort unterstützt Python vier verschiedene Möglichkeiten, dies zu tun.

Ich bin sicher, dass ich von einigen Diehards geflammt werde, aber der Compiler / Interpreter kümmert sich nicht darum, ob die Argumente lange oder kurze Namen haben, und - abgesehen von der Einrückungskonvention in Python - kümmert sich nicht um Leerzeichen. Das größte Problem mit Code besteht darin, einem anderen Menschen (und sogar Ihnen selbst nach Monaten der Arbeit) Klarheit zu geben, um zu verstehen, was vor sich geht, wo Dinge beginnen und enden usw.

eSurfsnake
quelle
5

Ein Zitat aus " When Pythons Attack "

Beenden Sie nicht alle Ihre Anweisungen mit einem Semikolon. Es ist technisch legal, dies in Python zu tun, aber es ist völlig nutzlos, wenn Sie nicht mehr als eine Anweisung in eine einzelne Zeile setzen (z. B. x = 1; y = 2; z = 3).

Kommunistischer Pfannkuchen
quelle
4
Warum nicht x,y,z = 1,2,3?
Anirban Nag 'tintinmj'
5
@ AnirbanNag'tintinmj 'In diesem speziellen Fall glaube ich, dass x, y, z = 1, 2, 3es langsamer ist, weil es eine unnötige Rundreise zum Erstellen eines Tupels verursacht und es dann sofort zerlegt. (Übrigens glaube ich nicht, dass @communistpancake das x=1; y=2; z=3Muster vorschlägt . Ich denke, er / sie gibt nur ein Beispiel dafür, wie Semikolon eher ein Trennzeichen als ein Terminator ist.)
RayLuo
1
@AnirbanNag - denn das wäre ein Müllbeispiel für eine Zeile mit mehreren Anweisungen gewesen.
cz
4

Mehrere Anweisungen in einer Zeile können Semikolons als Trennzeichen enthalten. Zum Beispiel: http://docs.python.org/reference/compound_stmts.html In Ihrem Fall können Sie auf einfache Weise einen Punkt einfügen, der in den Debugger eingebrochen werden soll.

Wie von Mark Lutz im Learning Python Book erwähnt , ist es technisch legal (obwohl unnötig und ärgerlich), alle Ihre Aussagen mit Semikolons zu beenden .

mandarg
quelle
2

Mit Python können Sie ein Semikolon verwenden, um das Ende einer Anweisung zu kennzeichnen, wenn Sie mehr als eine Anweisung in eine Zeile einfügen.

Godwin
quelle
2

Semikolons können für eine Zeile mit zwei oder mehr Befehlen verwendet werden. Sie müssen nicht verwendet werden, sind aber nicht eingeschränkt.

Das Semikolon (;) erlaubt mehrere Anweisungen in einer Zeile, da keine der Anweisungen einen neuen Codeblock startet.

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

Schädel leer
quelle
2

Semikolons (wie Punkte, Kommas und Klammern) neigen dazu, Religionskriege zu verursachen. Dennoch sind sie (oder ein ähnliches Symbol) aus verschiedenen Gründen in jeder Programmiersprache nützlich.

  • Praktisch: Die Möglichkeit, mehrere kurze Befehle, die konzeptionell zusammengehören, in derselben Zeile zu platzieren. Ein Programmtext, der wie eine schmale Schlange aussieht, hat den gegenteiligen Effekt von Zeilenumbrüchen und Einrückungen, wodurch die Struktur hervorgehoben wird.

  • Konzeptionell: Trennung von Bedenken zwischen reiner Syntax (in diesem Fall für eine Folge von Befehlen) und Präsentation (z. B. Zeilenumbruch), früher als "hübsches Drucken" bezeichnet.

Beobachtung: Zum Hervorheben der Struktur kann die Einrückung auf offensichtliche Weise durch vertikale Linien erweitert / ersetzt werden, die als "visuelles Lineal" dienen, um zu sehen, wo eine Einrückung beginnt und endet. Unterschiedliche Farben (z. B. Befolgen des Farbcodes für Widerstände) können die Überfüllung ausgleichen.

Raymond
quelle
1

Es ist erlaubt, weil die Autoren beschlossen haben, es zuzulassen: https://docs.python.org/2/reference/simple_stmts.html

Wenn Sie sich fragen, warum sich die Autoren dazu entschlossen haben, ist dies wahrscheinlich der Fall, da eine Halbspalte zumindest in den folgenden Sprachen als einfache Anweisungsbeendigung zulässig ist: C ++, C, C #, R, Matlab, Perl, ...

So ist es schneller, Python für Personen mit Hintergrund in einer anderen Sprache zu verwenden. Und es gibt keinen Verlust an Allgemeinheit bei einer solchen Entscheidung.

Bruziuz
quelle
1

Semikolon (";") wird nur für die Trennung von Anweisungen innerhalb desselben Blocks benötigt, z. B. wenn wir den folgenden C-Code haben:

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

Es kann in Python in einer der beiden Formen geschrieben werden:

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

Oder

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

Im obigen Beispiel können Sie eine beliebige Anzahl von Anweisungen innerhalb eines ifBlocks haben und durch ";" stattdessen.

Hoffe, dass nichts so einfach ist wie die obige Erklärung.

Mohd Asim
quelle
0

Zusätzlich zu den großen Wissen vorhanden hier
Dies ist eine Antwort auf die matplotlib Bibliothek bezogen

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

Wenn Sie am Ende des Balkens (horizontaler Balken) kein Semikolon angeben, ist die Ausgabe ein Plot + eine Funktionsadresse. Wenn Sie jedoch Semikolons am Ende beider Balkenzeilen verwenden, wird nur das Diagramm angezeigt und die Ausgabe für die Funktionsadresse unterdrückt.

So etwas in der Art: Vergleich

Farhan Khan
quelle
3
Dies ist spezifisch für IPython und gilt nicht für die Standard-Python-REPL.
Wjandrea
Ich denke, dies ist ein brillantes Beispiel, bei dem die Art und Weise, wie die Sprachautoren dachten, sie würden Einfachheit, Kraft und Einheitlichkeit einführen, die Probleme wie dieses nicht vorausdenken konnte.
eSurfsnake vor