Neden bu piton snippet'inde noktalı virgül kullanılmasına izin verilir?


166

Python, ifadeleri sonlandırmak için noktalı virgül kullanımını garanti etmez. Peki buna (aşağıda) neden izin veriliyor?

import pdb; pdb.set_trace()

1
Bu tür bir kodun sadece hata ayıklama amacıyla olduğunu ve "tamamlanmadan" tahmin edildiği gibi eksize edileceğini unutmayın. Bu pasajı olduğu gibi kullanıyorum, böylece kolayca hareket ettirebiliyorum.
Nick T

Lol Bu soruya aynı web sitesinden geldim
mackycheese21

Yanıtlar:


226

Python deyimleri sonlandırmak için noktalı virgül gerektirmez . Yarı kolonlar olabilir Eğer aynı satırda birden ifadeleri koymak istiyorsanız ifadeleri sınırlandırmak için kullanılabilir.

Şimdi, buna neden izin veriliyor? Basit bir tasarım kararı. Python'un bu iki nokta üst üste şeye ihtiyacı olduğunu sanmıyorum, ama biri sahip olmanın iyi olacağını düşündü ve dile ekledi.


16
Bu gibi şeyler için yararlıdırtimeit a = 5; a*a
Endolit

13
Exec deyimleri için yararlı gibi görünüyor, örneğin exec ('in [1,2,3]' de: print a; print a + 1 ')
Phil C

76
Python'a C, Obj-C, Javascript, PHP arka planıyla geldim. Sık sık (işe yaramaz) bir sonlandırıcı koydum; bir satırın sonunda. Ama neyse ki Python beni affeder
Paolo

36
Noktalı virgül, django kabuğunda veya hata ayıklayıcıda oldukça kullanışlıdır, böylece tek bir satıra küçük bir program yazıp daha sonra tekrarlayabilirsiniz.
Bryce

5
@endolith Ne anlama timeitgeliyor? hala 2 a = 2; a*aolduğu için işe yaramaz a; olması gerekeceka = 2; a *= a
Nearoo

59

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

Bileşik ifadeler bir veya daha fazla 'maddeden' oluşur. Bir cümle, bir başlık ve bir 'süit' öğesinden oluşur. Belirli bir bileşik ifadesinin yan tümce başlıkları aynı girinti düzeyindedir. Her yan tümce başlığı, benzersiz bir şekilde tanımlayıcı bir anahtar sözcükle başlar ve iki nokta üst üste ile biter. Suite, bir madde tarafından kontrol edilen bir ifade grubudur. Bir paket, başlık satırını izleyerek başlıkla aynı satırda noktalı virgülle ayrılmış bir veya daha fazla basit ifade olabilir veya sonraki satırlarda bir veya daha fazla girintili ifade olabilir . Yalnızca son süit formu iç içe bileşik ifadeler içerebilir; aşağıdakiler yasadışıdır, çünkü çoğunlukla başka bir cümle maddesinin hangi maddeye ait olduğu açık değildir:

if test1: if test2: print x

Ayrıca, noktalı virgülün bu bağlamda iki nokta üst üste işaretinden daha sıkı bağlandığını unutmayın, böylece aşağıdaki örnekte, yazdırma ifadelerinin tümü veya hiçbiri yürütülmez:

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

Özetleme:

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
Noktalı virgülün bir if'den sonra kolondan daha az önceliğini bilmiyordum. Teşekkürler!
gaborous

3
@gaborous Kişisel olarak yorumunuzun beni başka türlü ifade edeceğinizi düşündürecek kadar belirsiz hissediyorum. Yani, açıklığa kavuşturmak için, diğer okuyucuların resmi ifadeye sadıkif cond: stmt1; stmt2; stmt3
RayLuo

Evet, demek istediğim, öncelik daha azsa, lexer tüm noktalı virgül ifadeleri yürütülene kadar üst (iki nokta üst üste) bloğundan ayrılamaz. Bu gerçekten bariz bir şey değil.
gaborous

38

Python, ;sonlandırıcı değil, ayırıcı olarak kullanır . Bunları bir satırın sonunda da kullanabilirsiniz, bu da bir deyim sonlandırıcısı gibi görünmesini sağlar , ancak bu sadece yasal ifadelerin Python'da yasal olması nedeniyle geçerlidir - sonunda noktalı virgül içeren bir satır iki ifade, ikincisi bir boş.


28
Sonuna (veya herhangi bir yere) çift noktalı virgül koyarsanız, bir SyntaxError alırsınız. Yani boş ifadeler tamamen yasal değil gibi görünüyor.
Cucu

10
Muhtemelen listeler, tuples ile aynı mantığa sahiptir, sondaki virgüllerle dikte geçerlidir ve kesilmiş muadilleriyle aynıdır (örneğin [1,2,3] == [1,2,3,]) ancak çift virgül içeremezler . Yani temelde Python'un "sondaki boş çıkarıcısı" vardır. Bu arada bundan net:stmt_list ::= simple_stmt (";" simple_stmt)* [";"]
Cucu

@Cucu Haklısın. Ayrıca noktalı virgül içeren bir satır başlatamaz veya virgülle ifade listesi başlatamazsınız. Bu nedenle noktalı virgüllerin ve virgüllerin ayırıcılar ve isteğe bağlı sonlandırıcılar olduğunu söylemek daha doğru olur .
wjandrea

29

Yorumlayıcıda noktalı virgül

Cevapları okuduktan sonra, noktalı virgül kullanmanın önemli bir yönünü hala özlüyorum, muhtemelen gerçekten fark yarattığı tek nokta ...

Bir tercüman REPL'de (Python etkileşimli kabuk, IDLE, ipython) çalışırken, son ifadenin değeri ekrana yazdırılır ve genellikle bu amaçlanan davranıştır.

Yan etkiler için ifade kullanma

Ancak bazı durumlarda bir ifadeyi yalnızca yan etkileri açısından değerlendirmek istersiniz, örn. Simülasyonunuzun sonuçlarını görmek için matplotlib.

Bu durumda (muhtemelen) size screenful görmek istemiyoruz reprait s matplotlibbazen bir çağrı tarafından döndürülen nesneler matplotliben azından ipython içinde, işlev ve, sahip olasılıklardan biri bir noktalı virgül eklemek için aşırı ayrıntılı açıklamada, hemen ipython iki ifade, oluşan olarak giriş hattı gören matplotlibçağırma ve bir boş deyimi, bu bileşim, ifade değerdir Noneve hiçbir şey (diğer bir olasılık olarak yorumlayıcı tarafından ekrana yazdırılır atama olarak, _ = plot(...)ama bunu biraz daha müdahaleci buluyorum).

Kişisel açıklama

IMHO, yorumlayıcıda istenen çıktıyı bastırmak için noktalı virgül kullanımı, dokümantasyon ve nihai yeniden kullanım için bir tercüman oturumunun grafik çıktısı da dahil olmak üzere girdisini ve çıktısını kaydetmeye izin veren IPyton not defterinin tanıtımını takiben daha alakalı hale geldi. .


Anlıyorum, paylaştığın için teşekkürler! Noktalı virgülün ipython not defterinde matplotlib tarafından repr'yi önleyebileceği tam olarak sorunumu çözdü
Napitupulu Jon

Bu yalnızca IPython özelliğidir ve boş bir ifade değildir, yalnızca özel bir sözdizimidir.
wjandrea

@wjandrea Haklısın, bu sadece ipython... Yorumumu yansıtmak için cevabımı düzenledim.
gboffi

En yaygın kullanım örneği haline geldiğini düşündüğümden bu cevap daha yüksek olmalı (Jupyter notebook + IPython iş akışının yayılmasıyla)
Josh Friedlander

12

Herkes belirttiği gibi, sen yapabilirsiniz ifadeleri ayırmak için noktalı virgül kullanın. Sen yok olması için ve o zamanki tarzım değil.

Bunun neden faydalı olduğuna gelince, bazı insanlar iki veya daha fazla önemsiz kısa ifadeyi tek bir satıra koymayı severler (kişisel olarak bunun önemsiz, kolayca gözden kaçan hatları tek bir karmaşık görünümlü çizgiye dönüştürdüğünü ve önemsiz olduğunu görmeyi zorlaştırdığını düşünüyorum) .

Ancak, Python'u bir astarı kullanarak kabuktan çağırırken neredeyse bir gerekliliktir python -c '<some python code>'. Burada olamaz one-liner iki astar gerçekten eğer öyleyse, ayrı açıklamalarda girinti kullanmak, bir noktalı virgül kullanmanız gerekir. Ve tek astarınızda başka argümanlar kullanmak istiyorsanız, adrese syserişmek için içe aktarmanız gerekir sys.argv; bu da ayrı bir importifade gerektirir . Örneğin

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

2
Sen edebilirsiniz aracılığıyla komutları geçerken girinti ve yeni satır kullanmak pythonHemen çoklu hatları üzerinden teklif edilen kod yayılan veya yorumlu metin kullanın: kabukta. Yine de, "tek astar" olmasını istiyorsanız bu başarısız olur. ;)
00dani

ile demiryolu yanıtı için özellikler içerir-c
n611x007

6

Eski bir C programcısı olarak önyargılı olduğumu fark ettim, ancak çeşitli Python sözleşmelerinin takip edilmesini zorlaştırdığı zamanlar var. Girinti kuralını zaman zaman biraz can sıkıcı buluyorum.

Bazen, bir ifadenin veya bloğun ne zaman sona erdiğinin anlaşılması çok yararlı olur. Standart C kodu genellikle böyle bir şey okuyacaktır:

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

continue doing things;

beyazlığı çok fazla netlik için kullandığınız yerde - ve döngünün nerede bittiğini görmek kolaydır.

Python, (isteğe bağlı) noktalı virgülle sonlandırmanıza izin verir. Yukarıda belirtildiği gibi, bu bir "null" ifadesinin ardından yürütülecek bir ifade olduğu anlamına GELMEZ. Yani mesela,

print(x);
print(y);

Aynıdır

print(x)
print(y)

Birincisinin her satırın sonunda bir boş deyim olduğuna inanıyorsanız, - önerildiği gibi - bunu yapmayı deneyin:

print(x);;

Bir sözdizimi hatası atar.

Şahsen, çok sayıda yuvalama ve birçok argüman ve / veya uzun adlı argüman içeren işlevleriniz olduğunda kodu daha okunabilir hale getirmek için noktalı virgül buluyorum. Yani, gözlerime göre, bu diğer seçimlerden çok daha net:

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

çünkü bana göre, son ')' dizisinin birçok çizgiyi aşan bir 'bloğu' sona erdirdiğini bilmenizi sağlar.

Şahsen, PEP tarzı kurallardan, onları uygulayan IDE'lerden ve 'şeyleri yapmanın tek bir Pythonic yolu' olduğuna dair inançtan çok şey olduğunu düşünüyorum. İkincisine inanıyorsanız, sayıları nasıl biçimlendireceğinize bakın: şu andan itibaren Python bunu yapmak için dört farklı yolu desteklemektedir .

Bazı diehard'lar tarafından alevleneceğime eminim, ancak derleyici / yorumlayıcı, argümanların uzun veya kısa isimlere sahip olup olmadığını umursamıyor ve - ancak Python'daki girinti konvansiyonu için - boşluk umurunda değil. Koddaki en büyük sorun, neler olup bittiğini, olayların nerede başladığını ve bittiğini vb. Anlamak için başka bir insana (ve hatta aylarca çalıştıktan sonra kendinize) netlik vermektir.



5

" Pythons Saldırısı " ndan alıntı

Tüm ifadelerinizi noktalı virgülle sonlandırmayın. Python'da bunu yapmak teknik olarak yasaldır, ancak tek bir satıra birden fazla ifade yerleştirmediğiniz sürece tamamen işe yaramaz (örneğin, x = 1; y = 2; z = 3).


4
Neden olmasın x,y,z = 1,2,3?
Anirban Nag 'tintinmj'

5
@ AnirbanNag'tintinmj 'Bu özel durumda, x, y, z = 1, 2, 3daha yavaş olduğuna inanıyorum çünkü bir tuple inşa etmenin gereksiz bir turuna neden oluyor ve hemen onu anlıyor. (Bu arada, @communistpancake'ın x=1; y=2; z=3deseni önerdiğini gerçekten sanmıyorum . Sanırım sadece noktalı virgülün sonlandırıcıdan ziyade nasıl bir ayırıcı olduğuna dair bir örnek veriyor.)
RayLuo

1
@AnirbanNag - çünkü bu çok ifadeli bir çizginin çöp örneğiydi.
cz

4

Bir satırdaki birden fazla ifade, ayırıcı olarak noktalı virgül içerebilir. Örneğin: http://docs.python.org/reference/compound_stmts.html Sizin durumunuzda, hata ayıklayıcıya kırmak için bir noktanın kolayca eklenmesini sağlar.

Ayrıca, Mark Lutz tarafından Learning Python Book'ta belirtildiği gibi , tüm ifadelerinizi noktalı virgülle sonlandırmak teknik olarak yasaldır (gereksiz ve sinir bozucu) .


3

Python, bir satıra birden fazla ifade eklerseniz, ifadenin sonunu belirtmek için noktalı virgül kullanmanıza izin verir.



2

Noktalı virgüller (noktalar, virgüller ve parantezler gibi) dini savaşlara neden olma eğilimindedir. Yine de, bunlar (veya benzer bir sembol) çeşitli nedenlerle herhangi bir programlama dilinde yararlıdır.

  • Pratik: kavramsal olarak bir araya gelen birkaç kısa komutu aynı hatta koyma yeteneği. Dar bir yılan gibi görünen bir program metni, satırları vurgulayan satırsonu ve girinti ile amaçlananın tersi bir etkiye sahiptir.

  • Kavramsal: "güzel baskı" olarak adlandırılan eski günlerde, saf sözdizimi (bu durumda, bir dizi komut için) arasındaki kaygıların sunumdan (örn. Yeni satır) ayrılması.

Gözlem: yapıyı vurgulamak için, girintinin açık bir şekilde dikey çizgilerle artırılması / değiştirilmesi, girintinin nerede başladığını ve bittiğini görmek için bir "görsel cetvel" görevi görür. Farklı renkler (örn. Dirençler için renk kodunu takip ederek) kalabalıklaşmayı telafi edebilir.


1

İzin verilir, çünkü yazarlar izin vermeye karar verdiler: https://docs.python.org/2/reference/simple_stmts.html

Yazarların neden bunu yapmaya karar verdiğini sormak için hareket ederseniz, sanırım bu yüzden yarım sütuna en azından aşağıdaki dillerde basit bir deyim sonlandırması olarak izin verilir: C ++, C, C #, R, Matlab, Perl, ...

Bu nedenle, başka bir dilde geçmişi olan insanlar için Python kullanımına geçmek daha hızlıdır. Ve böyle bir kararda genelliği kaybetmez.


1

Noktalı virgül (";") yalnızca, aşağıdaki C koduna sahip olduğumuz gibi, aynı blok içindeki ifadelerin ayrılması için gereklidir:

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

Python'da iki formdan birinde yazılabilir:

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

Veya

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

Yukarıdaki örnekte, bir ifblok içinde istediğiniz sayıda ifade olabilir ve ";" ile ayrılabilir yerine.

Umarım hiçbir şey yukarıdaki açıklama kadar basit değildir.


0

Burada bulunan engin bilgiye ek olarak,
bu matplotlib kütüphanesi ile ilgili bir cevaptır

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 (yatay çubuk) sonunda noktalı virgül sağlamazsanız, çıktı bir çizim + bir işlev adresidir. Ancak her iki barh satırının sonunda noktalı virgül kullanırsanız, yalnızca grafiği gösterir ve işlev adresi çıktısını bastırır.

Böyle bir şey: Karşılaştırma


3
Bu IPython'a özgüdür ve standart Python REPL için geçerli değildir.
wjandrea

Bence bu, dil yazarlarının basitlik, güç ve bütünlük sağladıklarını düşündükleri yolun, bunun gibi sorunların ötesine geçemediği mükemmel bir örnek.
eSurfsnake
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.