Python 3 neden 0 için değişmez değer olarak "00" 'a izin verirken 1 için değişmez değer olarak "01" e izin vermez?


111

Python 3 neden 0 için değişmez değer olarak "00" a izin verirken 1 için değişmez değer olarak "01" e izin vermez? İyi bir sebep var mı? Bu tutarsızlık beni şaşırtıyor. (Ve tutarlılık gibi hedeflere ulaşmak için kasıtlı olarak geriye dönük uyumluluğu bozan Python 3'ten bahsediyoruz.)

Örneğin:

>>> from datetime import time
>>> time(16, 00)
datetime.time(16, 0)
>>> time(16, 01)
  File "<stdin>", line 1
    time(16, 01)
              ^
SyntaxError: invalid token
>>>

42
Şimdi kaldırılamaz, yoksa bu soruyla geriye dönük uyumluluğu bozar!
John La Rooy

Yanıtlar:


103

Başına https://docs.python.org/3/reference/lexical_analysis.html#integer-literals :

Tamsayı değişmezleri aşağıdaki sözcük tanımlarıyla açıklanır:

integer        ::=  decimalinteger | octinteger | hexinteger | bininteger
decimalinteger ::=  nonzerodigit digit* | "0"+
nonzerodigit   ::=  "1"..."9"
digit          ::=  "0"..."9"
octinteger     ::=  "0" ("o" | "O") octdigit+
hexinteger     ::=  "0" ("x" | "X") hexdigit+
bininteger     ::=  "0" ("b" | "B") bindigit+
octdigit       ::=  "0"..."7"
hexdigit       ::=  digit | "a"..."f" | "A"..."F"
bindigit       ::=  "0" | "1"

Mevcut bellekte saklanabilecekler dışında tamsayı değişmezlerinin uzunluğu için bir sınır yoktur.

Sıfır olmayan bir ondalık sayıdaki baştaki sıfırlara izin verilmediğini unutmayın. Bu, Python'un 3.0 sürümünden önce kullandığı C tarzı sekizlik değişmez değerlerle belirsizliği ortadan kaldırmak içindir.

Burada belirtildiği gibi, sıfır olmayan ondalık sayıdaki baştaki sıfırlara izin verilmez. Python 2'de olmayan"0"+ çok özel bir durum olarak yasaldır :

integer        ::=  decimalinteger | octinteger | hexinteger | bininteger
decimalinteger ::=  nonzerodigit digit* | "0"
octinteger     ::=  "0" ("o" | "O") octdigit+ | "0" octdigit+

SVN commit r55866 , eski 0<octal>sayıları yasaklayan belirteçte PEP 3127'yi uyguladı . Ancak ilginç bir şekilde şu notu da ekler:

/* in any case, allow '0' as a literal */

nonzeroYalnızca SyntaxErroraşağıdaki basamak dizisi sıfır olmayan bir rakam içeriyorsa a atan özel bir bayrak ile .

Bu garip çünkü PEP 3127 bu duruma izin vermiyor:

Bu PEP, başında sıfır kullanarak sekizlik bir sayı belirleme yeteneğinin Python 3.0'daki (ve 2.6'nın Python 3.0 önizleme modu) dilden kaldırılacağını ve baştaki "0" olduğunda bir SyntaxError oluşturulacağını önermektedir. hemen ardından başka bir rakam .

(vurgu benim)

Dolayısıyla, birden fazla sıfıra izin verilmesi, teknik olarak KEP'i ihlal ediyor ve temelde Georg Brandl tarafından özel bir durum olarak uygulandı. "0"+Geçerli bir vaka olduğunu belirtmek için ilgili dokümantasyon değişikliğini yaptı decimalinteger(daha önce kapsamında kapsanan octinteger).

Muhtemelen asla bilemeyeceğim tam Georg yapmak seçtim "0"+geçerli - sonsuza kadar Python garip bir köşe durumda kalabilir.


GÜNCELLEME [28 Temmuz 2015]: Bu soru, Georg'un dahil olduğu python fikirleri üzerine canlı bir tartışma başlığına yol açtı :

Steven D'Aprano şunu yazdı:

Neden bu şekilde tanımlandı? [...] Sıfır elde etmek için neden 0000 yazalım?

Sana söyleyebilirdim ama sonra seni öldürmek zorunda kalırım.

Georg

Daha sonra iş parçacığı , bu özel durumdan kurtulmayı amaçlayan bu hata raporunu ortaya çıkardı . Burada, Georg diyor :

Bu kasıtlı değişikliğin nedenini hatırlamıyorum (doküman değişikliğinden görüldüğü gibi).

Şu anda bu değişiklik için iyi bir neden bulamıyorum [...]

ve böylece bizde var: bu tutarsızlığın arkasındaki kesin sebep zamanla kayboldu.

Son olarak, hata raporunun reddedildiğine dikkat edin: Baştaki sıfırlar, Python 3.x'in geri kalanı için yalnızca sıfır tamsayılarda kabul edilmeye devam edecek.


6
Neden "Georg'un neden seçtiğini muhtemelen asla bilemeyeceğiz ..." diyorsunuz? Onu tanıyan biri bu konuyu görür ve onu bilgilendirirse, o zaman gelip cevabını verebilir! (geçmiş Python çalışmasını ya da benzer bir durumu tartışmayı sonsuza kadar reddettiğini bilmiyorsanız)
mors

1
Neden ikinci Python 2 octintegervakasını yapmadıklarını anlamıyorum "0" octdigit*. 0C / C ++ 'da sekizlik bir hazır bilgidir.
Random832

1
Aslında İngilizce bu konuda biraz belirsiz. "Başka" kelimesi "bir tane daha" anlamına gelebilir veya "farklı bir" anlamına gelebilir. PEP 3127'den kalınlaştırılmış alıntının geçerli bir İngilizce yorumu, "Baştaki bir '0' hemen ardından '0' dışında bir rakam geldiğinde bir Sözdizimi Hatası ortaya çıkacaktır" anlamına gelir. bu yorum, gerçek kod tarafından destekleniyor gibi görünse de), ancak her durumda, bu cümleye ek açıklama yapılmadan KEP'in teknik olarak ihlal edildiğini söylemenin doğru olduğunu düşünmüyorum.
GrandOpener

2
@GrandOpener: Bunun 001yasadışı olduğuna dikkat edin, oysa yorumunuz bunu yasal kılar (çünkü "hemen" kelimesinin anlamı oldukça açık olmalıdır).
nneonneo

İyi bir nokta. Dolayısıyla KEP kesinlikle ihlal edilmektedir; belirsiz olan, ihlal edildiği kesin doğadır. :)
GrandOpener

17

Bu özel bir durum ( "0"+)

2.4.4. Tamsayı değişmez değerleri

Tamsayı değişmezleri aşağıdaki sözcük tanımlarıyla açıklanır:

tamsayı :: = ondalık tamsayı | sekizinci | hexinteger | bininteger
ondalık tamsayı :: = sıfır basamaklı olmayan rakam * | "0" +
nonzerodigit :: = "1" ... "9"
digit :: = "0" ... "9"
octinteger :: = "0" ("o" | "O") sekizli basamak +
hexinteger :: = "0" ("x" | "X") onaltılı basamak +
bininteger :: = "0" ("b" | "B") bağlama +
octdigit :: = "0" ... "7"
hexdigit :: = basamak | "a" ... "f" | "A" ... "F"
bindigit :: = "0" | "1"

Dilbilgisine bakarsanız, bunun 0özel bir duruma ihtiyaç duyduğunu görmek kolaydır . +Yine de ' ' neden gerekli görüldüğünden emin değilim . Geliştirici posta listesine göz atma zamanı ...


Python2'de birden fazlasının bir 0olarak ayrıştırıldığını not etmek ilginçtir octinteger(sonuç yine de 0olsa)

ondalık tamsayı :: = sıfır basamaklı olmayan rakam * | "0"
sekizli sayı :: = "0" ("o" | "O") sekizli basamak + | "0" sekiz basamaklı +

1
Ve neden olduğu "0"+ve olmadığı hakkında bir fikriniz var "0"mı?
lejlot

1
@lejlot, henüz değil - ama ilgimi çekiyor. Kesinlikle şartnamenin bir parçası
John La Rooy

3

Python2, sekizlik sayıları belirtmek için baştaki sıfırı kullandı:

>>> 010
8

Bu (? Yanıltıcı) davranıştan kaçınmak için, Python3 açık önekleri gerektirir 0b, 0o, 0x:

>>> 0o10
8

15
Soru kalır: neden 00izin verilir? (Ve 000, 0000vb.)
Michael Geary

4
@MichaelGeary: Muhtemelen belirsiz olamayacağı için (00000000, tabandan bağımsız olarak 0'dır) ve onu kaldırmak gereksiz yere kodu kıracaktır. Hala tuhaf.
RemcoGerlich

5
@RemcoGerlich Eğer yanılmıyorsam, tabandan 01da 1bağımsızdır.
Holt

2
@Holt: ama "0" + "1" e izin vermek? çünkü özel bir durum muhtemelen daha kafa karıştırıcı olacaktır.
RemcoGerlich

4
@RemcoGerlich Asla olmayacağını söylemedim;) Sadece muğlak can't be ambiguousolamayacağı için argüman 01olmadığını söylüyordum. IMO, 00durum sadece özel bir durumdur, çünkü 0olmaması gereken budur.
Holt
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.