Чому в цьому фрагменті пітона дозволено крапку з комою?


166

Python не гарантує використання крапки з комою для завершення операторів. То чому це дозволено (нижче)?

import pdb; pdb.set_trace()

1
Зауважте, що такий код є явним лише для налагодження, і, ймовірно, його слід вирізати, перш ніж це буде зроблено. Я використовую цей фрагмент так само, як у вас є, щоб я міг легко переміщати його.
Нік Т

Lol Я прийшов до цього питання з того самого веб-сайту: realpython.com/python-debugging-pdb
mackycheese21

Відповіді:


226

Python не вимагає напівколонок для припинення операторів. Напівколони можна використовувати для розмежування висловлювань, якщо ви хочете розмістити декілька висловлювань в одному рядку.

Тепер, чому це дозволено? Це просте дизайнерське рішення. Я не думаю, що Python не потребує цієї напівколонки, але хтось подумав, що це було б добре, і він додав його до мови.


16
Це корисно для таких речей, якtimeit a = 5; a*a
ендоліт

13
Це здається корисним для операторів exec, наприклад, exec ('for a in [1,2,3]: print a; print a + 1')
Phil C

76
Я прийшов на Python з фоном C, Obj-C, Javascript, PHP. Я часто ставлю (марний) термінатор; в кінці рядка. Але на щастя, Python пробачив мені
Паоло,

36
Точка з комою дуже корисна в оболонці django або налагоджувачі, тому ви можете написати невелику програму на одному рядку і повторити її пізніше.
Брайс

5
@endolith Що timeitозначає? a = 2; a*aмарний, оскільки aвсе ще 2; мав би бутиa = 2; a *= a
Неаро

59

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

Складені висловлювання складаються з одного або декількох "застережень". Стаття складається із заголовка та "набору". Заголовки пропозицій певного складеного висловлювання знаходяться на одному рівні відступу. Кожен заголовок пункту починається з однозначно ідентифікуючого ключового слова і закінчується двокрапкою. Набір - це група висловлювань, що контролюються пунктом. Набір може бути одним або декількома простими виразками, розділеними крапкою з комою, у тому ж рядку, що й заголовок, за двокрапкою заголовка, або це може бути одне чи більше відступів у наступних рядках . Тільки остання форма набору може містити вкладені складені висловлювання; наступне є незаконним, здебільшого тому, що не було б зрозуміло, до якого пункту наступного пункту ще належить:

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

Так, я мав на увазі, якщо пріоритет менший, то лексер не може залишити батьківський (двокрапковий) блок, поки не будуть виконані всі крапки з комою. Це справді не очевидна річ.
габоровий

38

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


28
Якщо ви поставите подвійні крапки з комою (або де завгодно), ви отримаєте SyntaxError. Тож видається, що пусті заяви не є повністю законними.
Cucu

10
Ймовірно, він має таку ж логіку, що і списки, кортежі, дикти з проміжними комами є дійсними і такі ж, як і їх оброблені аналоги (наприклад, [1,2,3] == [1,2,3,]), але вони не можуть містити подвійних коми . Таким чином, Python в основному має "засіб для видалення порожніх". Що до речі видно з цього:stmt_list ::= simple_stmt (";" simple_stmt)* [";"]
Cucu

@Cucu Ви маєте рацію. Ви також не можете запустити рядок з крапки з комою або створити список виразів з комою. Точніше сказати, що крапки з комою та комами - це роздільники та необов'язкові термінатори.
wjandrea

29

Крапка з комою в перекладачі

Прочитавши відповіді, я все-таки пропускаю один важливий аспект використання крапки з комою, можливо, єдиний, де він дійсно має значення ...

Коли ви працюєте в інтерпретаторі REPL (інтерактивна оболонка Python, IDLE, ipython), значення останнього виразу виводиться на екран, і зазвичай це призначена поведінка.

Використання вираження для побічних ефектів

Але в деяких випадках ви хочете оцінити вираз лише на його побічні ефекти, наприклад, щоб побачити результати симуляції, побудовані на matplotlib .

У цьому випадку ви (мабуть) не хочете бачити скріншот reprs matplotlibоб'єктів, які іноді повертаються викликом до matplotlibфункції, і, принаймні, в IPython, одна з можливих можливостей - додавати крапку з комою до надмірно багатослівний оператор, тепер IPython бачить рядок введення як складений з двох виразів, matplotlibвиклику та нульового твердження, так що значення складеного виразу є Noneі нічого не друкується на екран інтерпретатором (інша можливість - призначення , як у _ = plot(...)але я вважаю це трохи більш настирливим).

Особисте зауваження

IMHO, використання крапки з комою для придушення непотрібного виводу в інтерпретаторі стало більш актуальним після введення ноутбука IPyton, що дозволяє зберігати вхід і вихід, включаючи графічний вихід, сеансу перекладача для документації та можливого повторного використання .


Я бачу, дякую вам за обмін! Це якраз вирішило мою проблему, де крапка з комою може запобігти репрінг від matplotlib у зошиті ipython
Napitupulu Jon

Це функція лише для IPython, і це не нульове твердження, а лише спеціальний синтаксис.
wjandrea

@wjandrea Ви маєте рацію, це просто ipython... Я відредагував свою відповідь, щоб відобразити ваше зауваження.
gboffi

Ця відповідь повинна бути вищою, оскільки я думаю, що це став найпоширенішим випадком використання (із поширенням ноутбука Юпітера + робочого процесу IPython)
Джош Фрідлендер

12

Як зазначали всі інші, ви можете використовувати крапки з комою для розділення виписок. Ви не маєте , і це не звичайний стиль.

Що стосується того, чому це корисно, деякі люди люблять ставити два чи більше справді тривіальних коротких висловлювань на один рядок (особисто я думаю, що це перетворює кілька тривіальних легко пропущених ліній в одну складну вигляд лінії і ускладнює бачення, що це тривіально) .

Але це майже обов'язкова вимога, коли ви використовуєте Python один лайнер із оболонки, використовуючи 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оболонку: просто переведіть кодований код на кілька рядків або використовуйте гередок. Але все-таки це не вдається, якщо ви хочете, щоб він був "однолінійним". ;)
00дані

включає ознаки для відповіді на залізницю з-c
n611x007

6

Я усвідомлюю, що я упереджений як старий програміст C, але бувають випадки, коли різні конвенції 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, які їх застосовують, і віра в те, що "існує лише один пітонічний спосіб робити речі". Якщо ви вірите останньому, перегляньте, як форматувати номери: на сьогоднішній день Python підтримує чотири різні способи це зробити.

Я впевнений, що мене будуть спалахувати деякі глухи, але компілятор / інтерпретатор байдуже, чи аргументи мають довгі чи короткі назви, і - але для конвенції відступу в Python - не хвилює пробіл. Найбільшою проблемою коду є надання ясності іншій людині (і навіть собі після місяців роботи), щоб зрозуміти, що відбувається, де починаються і закінчуються справи тощо.



5

Цитата з " Коли пітони атакують "

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


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 У вашому випадку, це дозволяє легко вставити крапку, щоб прорватися до налагоджувача.

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


3

Python дозволяє вам використовувати крапку з двокрапкою для позначення кінця висловлювання, якщо ви включаєте більше одного твердження на рядок.


2

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

Точка з комою (;) дозволяє в одному рядку декілька висловлювань, враховуючи, що жоден оператор не починає новий блок коду.

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


2

Точки з комою (як крапки, коми і дужки), як правило, викликають релігійні війни. Проте вони (або якийсь подібний символ) корисні в будь-якій мові програмування з різних причин.

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

  • Понятійне: розмежування питань між чистим синтаксисом (у даному випадку для послідовності команд) від презентації (наприклад, нового рядка), у старі часи називалося «симпатичним друком».

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


1

Це дозволено, оскільки автори вирішили дозволити це: https://docs.python.org/2/reference/simple_stmts.html

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

Тож швидше перейти до використання Python для людей, які мають іншу мову. І в такому заході немає втрати загальності.


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

Якщо ви не надаєте крапку з комою в кінці барха (горизонтальної смуги), вихід - це графік + адреса функції. Але якщо ви використовуєте крапки з комою в кінці обох рядків barh, то це лише показує графік і придушує вихід для адреси функції.

Щось подібне: Порівняння


3
Це специфічно для IPython і не застосовується до стандартного Python REPL.
wjandrea

Я думаю, що це геніальний приклад, коли те, як письменники мови думали, що вони запроваджують простоту, могутність та однаковість, не вдалося заздалегідь задуматися над проблемами, як ця.
eSurfsnake
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.