Değişken ek açıklamalar nedir?


84

Python 3.6 piyasaya sürülmek üzere. PEP 494 - Python 3.6 Sürüm Programı Aralık ayının sonundan bahsediyor, bu yüzden değişken ek açıklamalardan bahsettiklerini görmek için Python 3.6'daki Yenilikler konusuna baktım :

PEP 484 , tip ipuçları olarak da bilinen işlev parametrelerinin tür ek açıklamaları için standart getirmiştir. Bu PEP, sınıf değişkenleri ve örnek değişkenleri dahil olmak üzere değişken türlerine açıklama eklemek için Python'a sözdizimi ekler:

primes: List[int] = []

captain: str  # Note: no initial value!

class Starship:
     stats: Dict[str, int] = {}

Tıpkı işlev açıklamaları için olduğu gibi, Python yorumlayıcısı değişken notlara belirli bir anlam atfetmez ve bunları yalnızca __annotations__bir sınıfın veya modülün özel bir özniteliğinde saklar . Statik olarak yazılmış dillerdeki değişken bildirimlerin aksine, açıklama sözdiziminin amacı, soyut sözdizimi ağacı ve __annotations__öznitelik aracılığıyla üçüncü taraf araçlar ve kitaplıklar için yapılandırılmış tür meta verilerini belirtmenin kolay bir yolunu sağlamaktır .

Okuduklarımdan, Python 3.5'ten gelen tür ipuçlarının bir parçası, Python 3.5'te Tür ipuçları nelerdir ?

captain: strVe class Starshipörneği takip ediyorum ama sonuncusu hakkında emin değilim: Nasıl primes: List[int] = []açıklıyor? Tam sayılara izin verecek boş bir liste mi tanımlıyor?


10
Tip ipuçları yok değil her türlü denetimi yapmak. primes: List[int] = []sadece boş bir listedir primes = []. Fark olmasıdır iddia olduğunu primes anlamına gelir sadece içerirler ints ve 3. parti uygulamalar bu iddiayı doğrulamak için programınızı kontrol yazabilirsiniz, ama sadece yazma ile aynı olan herhangi bir piton yorumlayıcı kodu çalıştırdığınızda primes = []ve böylece yapıyor primes: List[int] = []; primes.append("string")hala geçerli.
Bakuriu

2
@Bakuriu evet, iyi nokta. Jim Fasarakis-Hilliard'ın Python 3.5'te Tür Nedir ipuçları , neden yazım ipuçlarıYazım denetleyicilere yardımcı olur, belgelere yardımcı olur ve IDE'lerin daha doğru ve sağlam araçlar geliştirmesine yardımcı olur . PEP 526 - Değişken Ek Açıklamalar için Sözdizimi'nden alınmış olan Python, dinamik olarak yazılmış bir dil olarak kalacaktır ve yazarlar, konvansiyonel bile olsa tür ipuçlarını zorunlu kılmak istemezler .
fedorqui

1
Bu sorunuzu yanıtlıyor mu? Python 3.5'te tür ipuçları nelerdir?
AMC

Yanıtlar:


48

Aradaki her şey :ve arasındaki her şey =bir tür ipucudur, bu primesnedenle aslında olarak tanımlanır List[int]ve başlangıçta boş bir listeye ayarlanır (ve statsbaşlangıçta olarak tanımlanan boş bir sözlüktür Dict[str, int]).

List[int]ve Dict[str, int]sonraki sözdiziminin bir parçası değildir, ancak bunlar Python 3.5 yazım ipuçları PEP'de zaten tanımlanmıştır. 3.6 PEP 526 - Değişken Ek Açıklamalar için Sözdizimi önerisi, yalnızca aynı ipuçlarını değişkenlere eklemek için sözdizimini tanımlar; daha önce, yorum içeren değişkenlere yalnızca tür ipuçları ekleyebiliyordunuz (örneğin primes = [] # List[int]).

Hem Listve Dictvardır Jenerik belirli (beton) içeriği ile bir liste veya sözlük eşleme belirten türleri.

Zira List, [...]listedeki her öğenin türü olan tek bir 'argüman' ( sözdizimindeki öğeler ) vardır. Çünkü Dict, ilk bağımsız değişken anahtar türü ve ikincisi değer türüdür. Dolayısıyla , listedeki tüm değerler primestam sayıdır ve sözlükteki tüm anahtar-değer çiftleri çiftlerdir ve dizeleri tam sayılarla eşler.stats(str, int)

Bkz typing.Listve typing.Dicttanımları, ilgili bölüme Generics yanı sıra, - PEP 483 tipi İpuçları Teorisi .

İşlevler üzerindeki tür ipuçları gibi, bunların kullanımı isteğe bağlıdır ve aynı zamanda ek açıklamalar olarak kabul edilir (bunlara iliştirilecek bir nesne olması koşuluyla, modüllerdeki globaller ve sınıflardaki nitelikler, ancak işlevlerdeki yereller değil) __annotations__öznitelik aracılığıyla iç gözlem yapabilirsiniz . Bu ek açıklamalara rastgele bilgiler ekleyebilirsiniz, kesinlikle ipucu bilgisi yazmakla sınırlı değilsiniz.

Teklifin tamamını okumak isteyebilirsiniz ; yeni sözdiziminin üzerinde ve ötesinde bazı ek işlevler içerir; bu tür açıklamaların ne zaman değerlendirileceğini, nasıl iç gözlem yapılacağını ve örneğin bir şeyin sınıf özniteliğine karşı örnek özniteliği olarak nasıl bildirileceğini belirtir.


1
Yazım ipuçlarını, kodun çalışma şeklini etkilemedikleri için (bir obj.__annotations__öznitelik dışında ) "makine tarafından okunabilir" yorumlar olarak değerlendirebilir miyim?
iBug

2
@iBug: açıklamalar, yine de insanlar tarafından okunabilir açıklamalar olduğu sürece, makine tarafından okunabilir yorumlardır. :-)
Martijn Pieters

59

Değişken ek açıklamalar nedir?

Değişken ek açıklamalar, # typeiçinde tanımlandıkları gibi yorumlardan sonraki adımdır PEP 484; bu değişikliğin arkasındaki mantık , KEP 526'nın ilgili bölümünde vurgulanmaktadır .

Yani, tipe ipucu vermek yerine:

primes = []  # type: List[int]

Türe doğrudan bir form atamasıyla açıklama eklemeye izin vermek için yeni sözdizimi tanıtıldı :

primes: List[int] = []

@Martijn'in belirttiği gibi, mevcut türleri kullanarak typingve onu boş bir listeye ilklendirerek tamsayıların bir listesini gösterir .

Ne gibi değişiklikler getiriyor?

Yapılan ilk değişiklik , karakterden sonra bağımsız olarak veya isteğe bağlı olarak ek açıklama eklerken aynı zamanda bir değer atarken bir türle bir ada açıklama eklemenize olanak tanıyan yeni sözdizimiydi: :

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

Yani söz konusu örnek:

   primes: List[int] = [ ]
#    ^        ^         ^
#  augtarget  |         |
#         expression    |
#                  expression (optionally initialize to empty list)

Yeni sözdizimiyle birlikte ek değişiklikler de getirildi; modüller ve sınıflar artık tip meta verilerinin eklendiği bir __annotations__özniteliğe sahiptir (işlevler PEP 3107 - İşlev Açıklamaları'ndan beri olduğu gibi ):

from typing import get_type_hints  # grabs __annotations__

Şimdi __main__.__annotations__beyan edilen türleri tutar:

>>> from typing import List, get_type_hints
>>> primes: List[int] = []
>>> captain: str
>>> import __main__
>>> get_type_hints(__main__)
{'primes': typing.List<~T>[int]}

captainşu anda görünmeyecek get_type_hintsçünkü get_type_hintsyalnızca bir modülden de erişilebilen türleri döndürür; yani, önce bir değere ihtiyacı var:

>>> captain = "Picard"
>>> get_type_hints(__main__)
{'primes': typing.List<~T>[int], 'captain': <class 'str'>}

Kullanmak print(__annotations__)gösterecektir, 'captain': <class 'str'>ancak gerçekten __annotations__doğrudan erişmemelisiniz .

Benzer şekilde, sınıflar için:

>>> get_type_hints(Starship)
ChainMap({'stats': typing.Dict<~KT, ~VT>[str, int]}, {})

A ChainMap, belirli bir sınıfa ilişkin ek açıklamaları (ilk eşlemede bulunur) ve sınıfında mro( {}nesne için sonraki eşlemelerde ) bulunan temel sınıflarda tanımlanan tüm açıklamaları almak için kullanıldığında kullanılır.

Yeni sözdizimiyle birlikte, ClassVarsınıf değişkenlerini belirtmek için yeni bir tür eklenmiştir. Evet, örneğinizdestats aslında bir örnek değişkeni , a değil ClassVar.

Onu kullanmaya zorlanacak mıyım?

Yazım ipuçlarında olduğu gibi PEP 484, bunlar tamamen isteğe bağlıdır ve tür denetleme araçları için (ve bu bilgilere dayanarak başka ne yapabileceğiniz) esas kullanım içindir. Python 3.6'nın kararlı sürümü piyasaya sürüldüğünde, gelecekte küçük ayarlamalar eklenebilir.

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.