Почему точка с запятой разрешена в этом фрагменте Python?

166

Python не гарантирует использование точек с запятой для завершения операторов. Так почему это (ниже) разрешено?

import pdb; pdb.set_trace()
canadadry
источник
1
Обратите внимание, что такой код явно используется только для целей отладки и, вероятно, будет удален до того, как он будет «готов». Я использую этот фрагмент так же, как у вас, чтобы я мог легко перемещать его.
Ник Т
Lol Я пришел к этому вопросу с того же сайта: realpython.com/python-debugging-pdb
mackycheese21

Ответы:

226

Python не требует точки с запятой для завершения операторов. Точки с запятой можно использовать для разделения операторов, если вы хотите поместить несколько операторов в одну строку.

Теперь, почему это разрешено? Это простое дизайнерское решение. Я не думаю, что Python нуждается в этой точке с запятой, но кто-то подумал, что было бы хорошо иметь ее, и добавил ее в язык.

Андре Карон
источник
16
Это полезно для таких вещей, какtimeit a = 5; a*a
эндолит
13
Это кажется полезным для операторов exec, например, exec ('для a в [1,2,3]: print a; print a + 1')
Phil C
76
Я пришел на Python с опытом работы с C, Obj-C, Javascript, PHP. Я часто ставлю (бесполезный) терминатор; в конце строки. Но, к счастью, Питон меня прощает
Паоло
36
Точка с запятой очень полезна в оболочке django или отладчике, поэтому вы можете написать небольшую программу в одну строку и повторить ее позже.
Брайс
5
@endolith Что timeitзначит? a = 2; a*aбесполезен, так aкак еще 2; это должно было бытьa = 2; a *= a
Nearoo
59

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

Составные операторы состоят из одного или нескольких «предложений». Предложение состоит из заголовка и «набора». Заголовки предложений конкретного составного оператора находятся на одном уровне отступа. Каждый заголовок предложения начинается с уникально идентифицирующего ключевого слова и заканчивается двоеточием. Комплект - это группа операторов, контролируемая предложением. Набор может состоять из одного или нескольких разделенных точкой с запятой простых операторов в той же строке, что и заголовок, после двоеточия заголовка, или это может быть один или несколько операторов с отступом в последующих строках . Только последняя форма набора может содержать вложенные составные операторы; следующее недопустимо, в основном потому, что не ясно, к какому условию относится следующий оператор else:

if test1: if test2: print x

Также обратите внимание, что точка с запятой в этом контексте связывается сильнее, чем двоеточие, поэтому в следующем примере выполняются либо все, либо ни один из операторов печати:

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

Подводя итог:

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)* [";"]
Чаун
источник
4
Не знал о приоритете точки с запятой меньше, чем двоеточие после if. Спасибо!
Габорист
3
@gaborous Я лично чувствую ваш комментарий достаточно двусмысленным, чтобы я думал, что вы имеете в виду другой путь. Поэтому, чтобы уточнить, я бы предпочел, чтобы другие читатели придерживались официальной фразы: в этом if cond: stmt1; stmt2; stmt3примере либо все, либо ни одно из утверждений не выполняются ".
RayLuo
Да, это то, что я имел в виду, если приоритет меньше, то лексер не может покинуть родительский блок (двоеточие), пока не будут выполнены все операторы точки с запятой. Это действительно не очевидная вещь.
gaborous
38

Python использует в ;качестве разделителя, а не терминатора. Вы также можете использовать их в конце строки, что делает их похожими на терминатор операторов, но это допустимо только потому, что в Python допустимы пустые операторы - строка, содержащая точку с запятой в конце, - это два оператора, второе один бланк

Kindall
источник
28
Если вы ставите двойные точки с запятой в конце (или где-либо еще), вы получаете SyntaxError. Так что, кажется, пустые заявления не совсем законны.
Cucu
10
Вероятно, он имеет ту же логику, что и списки, кортежи, дикты с запятыми и запятыми и их дубликаты (например, [1,2,3] == [1,2,3,]), но они не могут содержать двойные запятые. , Так что в основном у Python есть «трейлер для удаления пробелов». Что, кстати, ясно из этого:stmt_list ::= simple_stmt (";" simple_stmt)* [";"]
Cucu
@ Куку Ты прав. Вы также не можете начать строку с точки с запятой или начать список выражений с запятой. Поэтому точнее будет сказать, что точки с запятой и запятые являются разделителями и необязательными терминаторами.
wjandrea
29

Точка с запятой в переводчике

Прочитав ответы, я все еще скучаю по одному важному аспекту использования точек с запятой, возможно, единственному, где это действительно имеет значение ...

Когда вы работаете в интерпретаторе REPL (интерактивная оболочка Python, IDLE, ipython), значение последнего выражения выводится на экран, и обычно это предполагаемое поведение.

Использование выражения для побочных эффектов

Но в некоторых случаях вы хотите оценить выражение только для его побочных эффектов, например, чтобы увидеть результаты вашего моделирования, нанесенные на график matplotlib.

В этом случае вы (вероятно) не хотите видеть скрин reprс matplotlibобъектами, которые иногда возвращаются при вызове matplotlibфункции, и, по крайней мере, в IPython, одна из возможностей, которую вы имеете, это добавить точку с запятой к чрезмерно В многословном выражении теперь IPython видит строку ввода, состоящую из двух выражений, matplotlibвызова и пустого оператора, так что значение составного выражения равно Noneи ничего не выводится на экран интерпретатором (другой возможностью является назначение , как в _ = plot(...)но я нахожу это немного более навязчивым).

Личное замечание

ИМХО, использование точки с запятой для подавления нежелательных выводов в интерпретаторе стало более актуальным после появления записной книжки IPyton, которая позволяет сохранять ввод и вывод, включая графический вывод, сеанса интерпретатора для документации и возможного повторного использования. ,

gboffi
источник
Понятно, спасибо, что поделились! Это как раз и решило мою проблему, когда точка с запятой может предотвратить повторное воспроизведение с помощью matplotlib в записной книжке
ipython
Это функция только для IPython, и это не пустой оператор, а специальный синтаксис.
wjandrea
@wjandrea Вы правы, просто ipython... я отредактировал свой ответ, чтобы отразить ваше замечание.
Гбоффи
Этот ответ должен быть выше, так как я думаю, что он стал наиболее распространенным вариантом использования (с распространением рабочего процесса на ноутбуке Jupyter + IPython)
Джош Фридлендер,
12

Как все остальные заметили, вы можете использовать точки с запятой для разделения операторов. Вам не нужно , и это не обычный стиль.

Что касается того, почему это полезно, некоторым людям нравится помещать два или более действительно тривиальных коротких высказывания в одну строку (лично я думаю, что это превращает несколько простых тривиальных строк с легким скиммингом в одну сложную линию и затрудняет понимание того, что это тривиально) ,

Но это почти требование, когда вы вызываете Python one liners из оболочки, используя python -c '<some python code>'. Здесь вы не можете использовать отступ для разделения операторов, поэтому, если ваша строка содержит две строки, вам нужно использовать точку с запятой. И если вы хотите использовать другие аргументы в одной строке, вам придется импортировать, sysчтобы получить sys.argv, что требует отдельного importутверждения. например

python -c "import sys; print ' '.join(sorted(sys.argv[1:]))" 5 2 3 1 4
1 2 3 4 5
Бен
источник
2
Вы можете использовать отступы и переводы строк при передаче команд через pythonоболочку: просто поместите ваш код в несколько строк или используйте heredoc. Тем не менее, это терпит неудачу, если вы хотите, чтобы это было «одной строкой». ;)
30:14
включает в себя черты для железнодорожного ответа с-c
n611x007
6

Я понимаю, что я предвзятый как старый программист на Си, но бывают случаи, когда различные соглашения Python усложняют задачу. Я нахожу соглашение по отступам время от времени немного раздражающим.

Иногда ясность, когда оператор или блок заканчивается, очень полезна. Стандартный код C часто будет читать что-то вроде этого:

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

continue doing things;

где вы используете пробелы для большей ясности - и легко увидеть, где заканчивается цикл.

Python позволяет вам завершить (необязательно) точкой с запятой. Как отмечалось выше, это НЕ означает, что существует оператор для выполнения, за которым следует оператор 'null'. Так, например,

print(x);
print(y);

Такой же как

print(x)
print(y)

Если вы считаете, что первый из них имеет нулевое выражение в конце каждой строки, попробуйте - как было предложено - сделать это:

print(x);;

Это вызовет синтаксическую ошибку.

Лично я нахожу точку с запятой, чтобы сделать код более читабельным, когда у вас много вложений и функций со многими аргументами и / или аргументами с длинными именами. Итак, на мой взгляд, это намного яснее, чем другие варианты:

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

поскольку, для меня, это позволяет вам знать, что последний ')' заканчивает некоторый "блок", который пробегал много строк.

Лично я думаю, что многое из того, что сделано, основано на руководящих принципах стиля PEP, IDE, которые обеспечивают их соблюдение, и убеждение, что «есть только один Pythonic способ сделать что-то». Если вы верите последнему, посмотрите, как форматировать числа: на данный момент Python поддерживает четыре различных способа сделать это.

Я уверен, что я буду огорчен некоторыми несгибаемыми, но компилятор / интерпретатор не заботится о длинных или коротких именах аргументов, и - но для соглашения об отступах в Python - не заботится о пробелах. Самая большая проблема с кодом - дать ясность другому человеку (и даже вам самому после нескольких месяцев работы), чтобы понять, что происходит, где все начинается и заканчивается и т. Д.

eSurfsnake
источник
5

Цитата из « Когда нападают питоны »

Не заканчивайте все ваши утверждения точкой с запятой. Это технически допустимо делать в Python, но совершенно бесполезно, если вы не помещаете более одной инструкции в одну строку (например, x = 1; y = 2; z = 3).

CommunistPancake
источник
4
Почему нет x,y,z = 1,2,3?
Anirban Nag 'tintinmj'
5
@ AnirbanNag'tintinmj 'В данном конкретном случае я считаю, x, y, z = 1, 2, 3что это происходит медленнее, потому что он влечет за собой ненужное круговое движение при создании кортежа, а затем сразу же снимает его. (Между прочим, я не думаю, что @communistpancake предлагает x=1; y=2; z=3образец. Хотя я думаю, что он или она просто приводит пример того, как точка с запятой является разделителем, а не терминатором.)
RayLuo
1
@AnirbanNag - потому что это был бы глупый пример строки с несколькими утверждениями.
cz
4

Несколько операторов в одной строке могут содержать точки с запятой в качестве разделителей. Например: http://docs.python.org/reference/compound_stmts.html В вашем случае это позволяет легко вставить точку, которая пробивается в отладчике.

Кроме того, как отметил Марк Лутц в Книге изучения Python , технически законно (хотя это и не нужно и раздражает) завершать все ваши утверждения точкой с запятой.

mandarg
источник
3

Python позволяет вам использовать точку с запятой для обозначения конца оператора, если вы включаете более одного оператора в строку.

Годвин
источник
2

Точки с запятой можно использовать в одной строке двумя или более командами. Их не нужно использовать, но они не ограничены.

Точка с запятой (;) допускает несколько операторов в одной строке, если ни один из операторов не начинает новый блок кода.

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

craniumonempty
источник
2

Точки с запятой (как точки, запятые и скобки), как правило, вызывают религиозные войны. Тем не менее, они (или некоторый подобный символ) полезны в любом языке программирования по разным причинам.

  • Практичность: возможность поместить несколько коротких команд, концептуально принадлежащих друг к другу, в одну строку. Текст программы, который выглядит как узкая змея, имеет эффект, противоположный тому, что подразумевается под новыми строками и отступами, что выделяет структуру.

  • Концептуальное: разделение интересов между чистым синтаксисом (в данном случае для последовательности команд) и представлением (например, новой строкой), в старые времена называвшееся «симпатичной печатью».

Наблюдение: для выделения структуры отступ может быть очевидным образом дополнен / заменен вертикальными линиями, служа «визуальной линейкой», чтобы увидеть, где начинается и заканчивается отступ. Различные цвета (например, следуя цветовому коду для резисторов) могут компенсировать скученность.

Раймонд
источник
1

Это разрешено, потому что авторы решили разрешить это: https://docs.python.org/2/reference/simple_stmts.html

Если перейти к вопросу, почему авторы решили сделать это, я думаю, что это так, потому что полуколонна допускается как простое завершение оператора, по крайней мере, в следующих языках: C ++, C, C #, R, Matlab, Perl, ...

Так что быстрее переходить на использование Python для людей с опытом работы на другом языке. И в таком решении нет потери общности.

bruziuz
источник
1

Точка с запятой (";") необходима только для разделения операторов внутри одного блока, например, если у нас есть следующий код на C:

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

Это может быть написано на Python в любой из двух форм:

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

Или

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

В приведенном выше примере вы можете иметь любое количество операторов в ifблоке и могут быть разделены ";" вместо.

Надеюсь, что ничего не так просто, как объяснение выше.

Мохд Асим
источник
0

Добавление к обширным знаниям, присутствующим здесь,
это ответ, связанный с библиотекой 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')

Если вы не поставите точку с запятой в конце строки (горизонтальная черта), на выходе будет график + адрес функции. Но если вы используете точки с запятой в конце обеих строк строки, тогда он только показывает график и подавляет вывод для адреса функции.

Как то так: Сравнение

Фархан Хан
источник
3
Это характерно для IPython и не относится к стандартному Python REPL.
wjandrea
Я думаю, что это блестящий пример, когда авторы языка думали, что они вводят простоту, мощь и единообразие, и не могли думать о проблемах, подобных этой.
eSurfsnake