Por que o ponto-e-vírgula é permitido neste snippet de python?


166

Python não garante o uso de ponto e vírgula para finalizar instruções. Então, por que isso (abaixo) é permitido?

import pdb; pdb.set_trace()

1
Observe que esse código é flagrantemente apenas para fins de depuração e provavelmente seria excisado antes de ser "concluído". Eu uso esse trecho da mesma maneira que você o possui para que eu possa movê-lo facilmente.
Nick T

Lol Eu vim para esta questão a partir do mesmo site: realpython.com/python-debugging-pdb
mackycheese21

Respostas:


225

O Python não requer ponto -e-vírgula para finalizar instruções. Ponto e vírgula pode ser usado para delimitar instruções, se você deseja colocar várias instruções na mesma linha.

Agora, por que isso é permitido? É uma decisão de design simples. Eu não acho que o Python precise dessa coisa de ponto-e-vírgula, mas alguém pensou que seria bom ter e o adicionou à linguagem.


16
É útil para coisas comotimeit a = 5; a*a
endólito 23/05

13
Parece útil para instruções exec, por exemplo, exec ('para a em [1,2,3]: imprima a; imprima a + 1')
Phil C

75
Eu vim para Python com experiência em C, Obj-C, Javascript, PHP. Costumo colocar um terminador (inútil); no final de uma linha. Mas, felizmente, Python me perdoa
Paolo

36
O ponto-e-vírgula é altamente útil no shell do django ou no depurador, para que você possa escrever um pequeno programa em uma única linha e repeti-lo mais tarde.
Bryce

5
@endolith O que timeitsignifica? a = 2; a*aé inútil, pois aainda é 2; ele teria que sera = 2; a *= a
Nearoo

58

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

As declarações compostas consistem em uma ou mais 'cláusulas'. Uma cláusula consiste em um cabeçalho e um 'conjunto'. Os cabeçalhos da cláusula de uma instrução composta específica estão todos no mesmo nível de indentação. Cada cabeçalho da cláusula começa com uma palavra-chave de identificação exclusiva e termina com dois pontos. Um conjunto é um grupo de instruções controladas por uma cláusula. Um conjunto pode ser uma ou mais instruções simples separadas por ponto-e-vírgula na mesma linha que o cabeçalho, após os dois pontos do cabeçalho, ou pode ser uma ou mais instruções recuadas nas linhas subseqüentes . Somente a última forma de suíte pode conter instruções compostas aninhadas; o seguinte é ilegal, principalmente porque não seria claro a que cláusula if se pertenceria uma cláusula else:

if test1: if test2: print x

Observe também que o ponto-e-vírgula se liga mais estreitamente que os dois pontos neste contexto, para que, no exemplo a seguir, todas ou nenhuma das instruções print sejam executadas:

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

Resumindo:

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
Não sabia que a prioridade do ponto e vírgula era menor que dois pontos depois de um if. Obrigado!
gaborous

3
@gaborous Pessoalmente, sinto seu comentário ambíguo o suficiente para me fazer pensar que você significaria o contrário. Portanto, para esclarecer, eu prefiro sugerir que outros leitores se apeguem à frase oficial: nesse if cond: stmt1; stmt2; stmt3exemplo, todas ou nenhuma das instruções é executada ".
RayLuo

Sim, foi isso que eu quis dizer, se a prioridade for menor, o lexer não poderá deixar o bloco pai (dois pontos) até que todas as instruções de ponto e vírgula sejam executadas. Isso realmente não é uma coisa óbvia.
gaborous

38

Python usa o ;como um separador, não um terminador. Você também pode usá-los no final de uma linha, o que os faz parecer um terminador de instruções, mas isso é legal apenas porque instruções em branco são legais em Python - uma linha que contém um ponto-e-vírgula no final são duas instruções, a segunda um espaço em branco.


28
Se você colocar ponto-e-vírgula duplo no final (ou em qualquer lugar), você obterá um SyntaxError. Parece que declarações em branco não são totalmente legais.
Cucu

10
Provavelmente, tem a mesma lógica que listas, tuplas, ditados com vírgulas à direita são válidas e as mesmas que suas contrapartes aparadas (por exemplo, [1,2,3] == [1,2,3,]), mas não podem conter vírgulas duplas . Então, basicamente, o Python tem um "removedor de rastreio em branco". Que por sinal é claro a partir desta:stmt_list ::= simple_stmt (";" simple_stmt)* [";"]
Cucu

@Cucu Você está certo. Você também não pode iniciar uma linha com ponto-e-vírgula ou iniciar uma lista de expressões com vírgula. Portanto, é mais preciso dizer que ponto e vírgula e vírgulas são separadores e terminadores opcionais.
wjandrea

28

Ponto e vírgula no intérprete

Depois de ler as respostas, ainda sinto falta de um aspecto importante do ponto e vírgula, possivelmente o único em que realmente faz a diferença ...

Quando você está trabalhando em um intérprete REPL (o shell interativo Python, IDLE, ipython), o valor da última expressão é impresso na tela e, geralmente, esse é o comportamento pretendido.

Usando uma expressão para efeitos colaterais

Mas, em alguns casos, você deseja avaliar uma expressão apenas para seus efeitos colaterais, por exemplo, para ver os resultados de sua simulação plotados por matplotlib.

Nesse caso, você (provavelmente) não deseja ver a tela cheia de repr s de matplotlibobjetos que às vezes são retornados por uma chamada para uma matplotlibfunção e, pelo menos no IPython, uma das possibilidades que você tem é acrescentar um ponto-e-vírgula ao valor excessivo. instrução detalhada , agora o IPython vê a linha de entrada composta por duas expressões, a matplotlibinvocação e uma instrução nula, de modo que o valor da expressão composta é Nonee nada é impresso na tela pelo intérprete (a outra possibilidade é a atribuição , como em _ = plot(...)mas acho isso um pouco mais intrusivo).

Observação pessoal

IMHO, o uso do ponto-e-vírgula para suprimir a saída não desejada no intérprete tornou-se mais relevante após a introdução do notebook IPyton, que permite salvar a entrada e a saída, incluindo a saída gráfica, de uma sessão de intérprete para documentação e eventual reutilização .


Entendo, obrigado por compartilhar! Este acabou de resolver exatamente o meu problema, onde vírgula pode impedir repr por matplotlib em ipython notebook
Napitupulu Jon

Este é um recurso exclusivo do IPython, e não é uma declaração nula, apenas uma sintaxe especial.
wjandrea

@wjandrea Você está correto, é apenas ipython... Eu editei minha resposta para refletir sua observação.
gboffi 03/06

12

Como todo mundo observou, você pode usar ponto e vírgula para separar as instruções. Você não precisa , e não é o estilo usual.

Quanto ao motivo pelo qual isso é útil, algumas pessoas gostam de colocar duas ou mais declarações curtas realmente triviais em uma única linha (pessoalmente, acho que isso transforma várias linhas triviais e facilmente passadas em uma única linha de aparência complexa e torna mais difícil ver que é trivial) .

Mas é quase um requisito quando você está chamando os liners Python a partir do shell usando python -c '<some python code>'. Aqui você não pode usar o recuo para separar as instruções. Portanto, se o seu one-liner é realmente de dois, você precisará usar um ponto-e-vírgula. E se você quiser usar outros argumentos em uma linha, precisará importar syspara obter sys.argv, o que exige uma importdeclaração separada . por exemplo

python -c "import sys; print ' '.join(sorted(sys.argv[1:]))" 5 2 3 1 4
1 2 3 4 5

2
Você pode usar indentação e novas linhas ao passar comandos pythonno shell: basta estender o código citado por várias linhas ou usar um heredoc. Ainda assim, isso falhará se você quiser que seja "uma linha". ;)
00dani 30/01

inclui traços para a resposta ferroviária com-c
n611x007

6

Percebo que sou tendencioso como um programador C antigo, mas há momentos em que as várias convenções do Python tornam as coisas difíceis de seguir. Às vezes, acho a convenção de travessia um pouco aborrecida.

Às vezes, a clareza de quando uma instrução ou bloco termina é muito útil. O código C padrão geralmente lê algo como isto:

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

continue doing things;

onde você usa o espaço em branco para obter mais clareza - e é fácil ver onde o loop termina.

O Python permite que você termine com um ponto e vírgula (opcional). Como observado acima, isso NÃO significa que há uma instrução a ser executada seguida por uma instrução 'nula'. SO, por exemplo,

print(x);
print(y);

É o mesmo que

print(x)
print(y)

Se você acredita que o primeiro tem uma declaração nula no final de cada linha, tente - como sugerido - fazendo o seguinte:

print(x);;

Irá gerar um erro de sintaxe.

Pessoalmente, acho que o ponto-e-vírgula torna o código mais legível quando você tem muitos aninhamentos e funções com muitos argumentos e / ou argumentos de nome longo. Então, a meu ver, isso é muito mais claro do que outras opções:

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

pois, para mim, você sabe que o último ')' termina algum 'bloco' que passou por muitas linhas.

Pessoalmente, acho que há muito a ser feito nas diretrizes de estilo PEP, IDEs que as aplicam e a crença de que existe "apenas uma maneira pitônica de fazer as coisas". Se você acredita no último, veja como formatar números: a partir de agora, o Python suporta quatro maneiras diferentes de fazê-lo.

Tenho certeza de que serei inflamado por alguns problemas, mas o compilador / intérprete não se importa se os argumentos têm nomes longos ou curtos e - mas para a convenção de indentação em Python - não se preocupa com espaços em branco. O maior problema com o código é dar clareza a outro humano (e até a você mesmo depois de meses de trabalho) para entender o que está acontecendo, onde as coisas começam e terminam etc.



5

Uma citação de " When Pythons Attack "

Não encerre todas as suas declarações com ponto e vírgula. É tecnicamente legal fazer isso no Python, mas é totalmente inútil, a menos que você esteja colocando mais de uma instrução em uma única linha (por exemplo, x = 1; y = 2; z = 3).


4
Por que não x,y,z = 1,2,3?
Anirban Nag 'tintinmj'

5
@ AnirbanNag'tintinmj 'Nesse caso em particular, acredito que x, y, z = 1, 2, 3seja mais lento, pois incorre em uma viagem de ida e volta desnecessária na construção de uma tupla e, em seguida, a envia imediatamente. (A propósito, eu realmente não acho que @communistpancake está sugerindo o x=1; y=2; z=3padrão. Acho que ele / ela está apenas dando um exemplo de como ponto-e-vírgula é um separador e não um terminador.)
RayLuo

1
@AnirbanNag - porque isso teria sido um exemplo de lixo de uma linha de declarações múltiplas.
CZ


2

O Python permite que você use um ponto-e-vírgula para indicar o final de uma instrução se você estiver incluindo mais de uma instrução em uma linha.



2

Ponto e vírgula (como pontos, vírgulas e parênteses) tendem a causar guerras religiosas. Ainda assim, eles (ou algum símbolo semelhante) são úteis em qualquer linguagem de programação por vários motivos.

  • Prático: a capacidade de colocar vários comandos curtos que pertencem conceitualmente juntos na mesma linha. Um texto de programa que se parece com uma cobra estreita tem o efeito oposto ao pretendido por novas linhas e recuo, o que está destacando a estrutura.

  • Conceitual: separação de preocupações entre sintaxe pura (neste caso, para uma sequência de comandos) e apresentação (por exemplo, nova linha), antigamente chamada de "impressão bonita".

Observação: para destacar a estrutura, o recuo pode ser aumentado / substituído por linhas verticais da maneira óbvia, servindo como uma "régua visual" para ver onde um recuo começa e termina. Cores diferentes (por exemplo, seguindo o código de cores para resistores) podem compensar a aglomeração.


1

É permitido porque os autores decidiram permitir: https://docs.python.org/2/reference/simple_stmts.html

Se passarmos a questionar por que os autores decidiram fazer isso, acho que é porque a semicoluna é permitida como final de instrução simples, pelo menos nos seguintes idiomas: C ++, C, C #, R, Matlab, Perl, ...

Portanto, é mais rápido mudar para o uso do Python para pessoas com experiência em outra linguagem. E não há perda de generalidade nesse julgamento.


1

O ponto e vírgula (";") é necessário apenas para a separação de instruções em um mesmo bloco, como se tivéssemos o seguinte código C:

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

Pode ser escrito em Python em uma das duas formas:

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

Ou

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

No exemplo acima, você pode ter qualquer número de instruções em um ifbloco e pode ser separado por ";" em vez de.

Espero que nada seja tão simples quanto a explicação acima.


0

Adicionando ao vasto conhecimento presente aqui,
esta é uma resposta relacionada à biblioteca 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')

Se você não fornecer um ponto-e-vírgula no final do barh (barra horizontal), a saída será um gráfico + um endereço de função. Mas se você usar ponto e vírgula no final de ambas as linhas barh, ele mostrará apenas o gráfico e suprimirá a saída do endereço da função.

Algo assim: Comparação


3
Isso é específico do IPython e não se aplica ao Python REPL padrão.
wjandrea

Penso que este é um exemplo brilhante em que a maneira como os autores da linguagem pensaram que estavam introduzindo simplicidade, poder e uniformidade não conseguiu pensar em problemas futuros como este.
eSurfsnake 16/07
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.