Bu garip kolon davranışı ne yapıyor?


105

Python 3.6.1 kullanıyorum ve çok garip bir şeyle karşılaştım. Bulmam uzun zaman alan basit bir sözlük atama yazım hatası yaptım.

context = {}
context["a"]: 2
print(context)

Çıktı

{}

Kod ne context["a"]: 2yapıyor? SyntaxErrorIMO olması gerektiği zaman bir yükseltmez . İlk başta bunun bir dilim yarattığını düşündüm. Bununla birlikte, yazmak repr(context["a"]: 2)bir SyntaxError. Ayrıca context["a"]: 2konsola da yazdım ve konsol hiçbir şey yazdırmadı. Geri dönebileceğini düşündüm Noneama o kadar emin değilim.

Ayrıca tek satırlık if ifadesi olabileceğini düşündüm, ancak bu da doğru sözdizimi olmamalı.

Ek olarak, context["a"]bir KeyError.

Kafam karıştı. Ne oluyor?


2
Zaten bu sorunun bir kopyası var ve bu Python acemileri için kafa karıştırıcı olduğu oldukça açık. Sanırım bu en kötüsü, eğer Python sizin tek dilinizse, burada tip ipucu verme ve başlatma öncesi değişken tanımlaması genel olarak yabancı hissedebilir. Bu davranış kasıtlı olduğundan ve bazen PEP 526'da açıklandığı gibi yararlı olduğundan ve uyumluluğu bozmak istemediğiniz için bir hatanın ortaya çıkarılmasının imkansız olduğunu hayal ediyorum. Bununla birlikte, Python geliştiricilerinin bazı durumlarda faydalı bir uyarı mesajı eklemeyi düşünüp düşünmeyeceğini merak ediyorum.
Chris_Rands

Yanıtlar:


98

Yanlışlıkla sözdizimsel olarak doğru bir değişken not yazdınız . Bu özellik Python 3.6'da tanıtıldı (bkz. PEP 526 ).

Bir değişken ek açıklaması, açıklamalı bir atamanın parçası olarak çözümlense de , atama ifadesi isteğe bağlıdır :

annotated_assignment_stmt ::=  augtarget ":" expression ["=" expression]

Böylece context["a"]: 2

  • context["a"] ek açıklama hedefi
  • 2 ek açıklamanın kendisi
  • context["a"] başlatılmamış

PEP, "ek açıklamanın hedefinin, en azından sözdizimsel olarak herhangi bir geçerli tek atama hedefi olabileceğini belirtir (bununla ne yapılacağı tür denetleyicisine bağlıdır)" , bu da anahtarın olması için var olması gerekmediği anlamına gelir. açıklamalı (dolayısıyla hayır KeyError). Orijinal PEP'den bir örnek:

d = {}
d['a']: int = 0  # Annotates d['a'] with int.
d['b']: int      # Annotates d['b'] with int.

Normalde, açıklama ifadesi olmalıdır ek açıklamaların ana kullanım tipi ipucu, ancak zorlanmaz sonuçta - Python türüne değerlendirir. Ek açıklama , sonucun türü veya değerinden bağımsız olarak herhangi bir geçerli Python ifadesi olabilir .

Gördüğünüz gibi, şu anda yazım ipuçları çok hoşgörülüdür ve mypy gibi statik bir tür denetleyiciniz yoksa nadiren faydalıdır. .


12
O halde bunun bir =atama operatörü gerektirmesi gerekmez mi? Anahtar mevcut değil. Bu bana yanlış geliyor.
justengel

1
Bu durumda, : bir atama operatörü. Sadece bir tür ek açıklaması "atıyoruz", anahtar değil. Buna izin vermek için herhangi bir sebep olduğundan şüpheliyim, sadece ek açıklama sözdizimini eklemenin istenmeyen bir yan etkisi.
chepner

1
@chepner Görünüşe göre bu bir yan etki imho değil. Bu tam olarak ilgili PEP'in yapmak için tasarlandığı şeydir.
Ma 0

6
Henüz tanımlanmamış bir hedefe açıklama eklemenize izin vermesi garip. İlk satırım ise x: strve hemen ardından type(x)gelirse, tercüman bir NameError. IMO sözdiziminin zorlaması gereken nesnenin önceden tanımlanmış veya yerinde tanımlanmış olması gerekir. Bu sadece kafa karışıklığı yaratır.
r.ook

2
@Idlehands Bu yine de amacı bozuyor. x = 'i am a string'Önceden sahip olmak x: strikinci tür gereksiz hale getirir .. Bu hiç eklenmemeliydi. Yorum olarak iyiydi; Asla öyle ya da böyle kullanıldığını göstermedim.
Ma 0
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.