Python sözlükleri python3.7 için neden geri alınamaz?


11

3.7'den başlayarak, standart python sözlüklerinin kampanya siparişini koruyacağı garanti edilmektedir. (*)

d = {'b': 1, 'a': 2}
for k in d: 
    print(k)
# Prints always 'b' before 'a'.

Başka bir deyişle, dikte tuşları sıkı bir sırada tutulur. Prensip olarak, bu anahtarların geri çevrilebilir olmasına izin verecektir. Ancak, aşağıdakilerin hiçbiri işe yaramaz:

# TypeError: 'dict' object is not reversible
for k in reversed(d): 
    print(k)

# TypeError: 'dict_keys' object is not reversible
for k in reversed(d.keys()): 
    print(k)

Sorular: Bu davranışın ardındaki neden nedir? Kararlar neden tersine çevrilemedi? Gelecekte bu davranışı değiştirme planları var mı?

Elbette geçici çözüm işe yarıyor:

for k in reversed(list(d.keys())): 
    print(k)

Tartışıldığı üzere (*) Nitekim, bu durumda, piton 3.6 tipik yüklemeler için zaten bu yazı .


Güncelleme : Python 3.8 ile başlayan dikte aslında tersine çevrilebilir. Kabul edilen cevap, Guido ve diğer temel geliştiriciler arasındaki bu karara yol açan tartışmayı ifade eder. Özetle, dil tutarlılığını uygulama çabalarına ve kullanıcılar için gerçek faydalara karşı ağırlıklandırdılar.

Yanıtlar:


5

Gönderen docs :

ters ( sıra )

Tersini döndür iterator. seq, bir __reversed__()yöntemi olan veya dizi protokolünü destekleyen bir yöntem olmalıdır ( __len__()yöntem ve __getitem__()0'dan başlayan tamsayı bağımsız değişkenleri olan yöntem).

Bir dictnesne uygulamaz __reversed__. Her iki yöntemi de uygular. Ancak, __getitem__anahtarları tamsayı yerine argüman olarak alır (0'dan başlayarak).

Neden olarak, bu zaten burada önerilmiş ve tartışılmıştır .

DÜZENLE:

Bu alıntılar Python-Dev posta listesindendir (25.'de başlayan "dict için __reversed__ yöntemleri ekle" dizisi, "kavramsal" argümanlarla başlayacağım, ilki Antoine Pitrou'dan:

OrderedDict'in reversed () işlevini zaten desteklediği hiçbir şeye değmez. Argüman her iki yönde de olabilir:

  1. dict bugünlerde OrderedDict ile benzer, bu yüzden de ters ();

  2. sipariş vermeyi önemsediğinizi açıkça belirtmek için OrderedDict kullanabilirsiniz; dikte etmek için bir şey eklemeye gerek yok.

Benim düşüncem, düzenli zorlamalar için garantili yerleştirme düzeninin yepyeni olması, bu nedenle kavramın yerleşmesi ve zorluklar hakkında günlük düşüncenin bir parçası olması biraz zaman alacak. Bu gerçekleştiğinde, kullanım örneklerinin ortaya çıkması ve __reversed__'nin bir noktada eklenmesi muhtemelen kaçınılmazdır. Uygulama basit görünüyor ve sınırlı bir koleksiyonun tersine çevrilebilir olmasını beklemek pek kavramsal bir sıçrama değil.

Ardından Raymond Hettinger'ın cevabı:

Diktelerin artık ekleme sırasını izlediği göz önüne alındığında, en son eklemeleri bilmek (yani bir görev diktesindeki en son eklenen görevler arasında geçiş yapmak) makul görünmektedir. Diğer olası kullanım örnekleri büyük olasılıkla Unix kuyruk komutunu nasıl kullandığımıza karşılık gelecektir.

Bu kullanım durumları ortaya çıkarsa, __reversed__'nin zaten desteklenmesi iyi olur, böylece insanlar popitem () çağrılarını ve ardından yeniden yerleştirmeleri kullanarak çirkin bir geçici çözüm uygulamak için cazip olmaz.

Posta listesine ifade asıl sorun oldu bu çok fazla kabartmak eklemek veya en azından bazı uygulamalarda (çift bağlı listeler yerine tek başına bağlantılı olanlar zorunda) bellek verimliliğini azaltacağını, burada Python hata izleyiciden inada Naoki en tırnak (var konu 33462 ):

"Sipariş vermek", "geri alınabilir" anlamına gelmez. Örneğin, tek bağlantılı liste sipariş edilir, ancak geri döndürülemez.

CPython uygulaması verimli sağlayabilirken __reverse__, tüm Python uygulamasının bunu sağlaması beklendiği __reverse__anlamına gelir . Örneğin, bazı Python uygulamaları hashmap + tek bağlantılı listeyle dikte uygulayabilir. Eklenirse , artık mümkün değil.__reverse__

Posta listesine geri dönelim, son iki mesaj (her ikisi de 08.06.2018 tarihinde yayınlanmıştır). Birincisi Michael Selik'ten:

Oybirliğinin v3.8'e dahil edilmek için +1 olduğunu söylerken doğru muyum?

Konudaki son nokta, çeşitli uygulamaları araştıran ve bu özelliği 3.8'e dahil etmenin uygun olduğuna karar veren INADA Naoki idi. Anladığım kadarıyla Guido, INADA'nın MicroPython'un v3.7 uygulamasını beklemesine ilişkin tavsiyesine katılıyordu. INADA fikrini değiştirdiğinden, her şeyin lehte olduğunu tahmin ediyorum.

Guido van Rossum'un mesajıyla sonuçlanıyor:

Bana doğru geliyor. Daha sonra durumun böyle olduğu iki sürümümüz olacak:

  • 3.6 CPython'da ancak dil spesifikasyonunda sipariş korumanın uygulandığı

  • 3.7 dil diline de eklendi

Diğer cevap ve yorumlarda belirtildiği gibi, reversed()3.8 (14.10.2018) sürümünden bu yana hem dikte hem de dikte için desteklenmektedir.


5
İkinci teklifiniz bu konunun önyargı seçimine benziyor. Oybirliği, işlevselliğin 3.8'de ekleneceği anlaşılıyor. Ayrıca python dictreversed
3.7'den

Kavgada bir köpeğim yok, sadece ilk tepkisini alıntıladım. Ama haklısın, nokta iyi alınmış - alıntıyı kaldırdım.
Gst

1
Teşekkürler. Python-dev'in tartışma konusu açığa çıktı. Nitekim, özellik sadece iki gün önce (14 Ekim 2019) piyasaya sürülen python 3.8'de zaten uygulandı.
normanius


Dokümanlar alıntısı yararlı değil, sadece bir sonraki soruya yalvarıyor "peki, neden dict tipi uygulanmıyor __reversed__?" Python-dev bağlantısı yararlı içeriğe sahiptir, ancak ilgili parçalar doğrudan cevapta çoğaltılmalıdır (bu tür saha dışı bağlantılar çürümeye eğilimlidir).
wim


1

Python 3.8 için güncelleme

Dict ve dictviews şimdi tersine çevrilmiş () kullanılarak tersine çevrilmiş kampanya siparişinde tekrarlanabilir

>>> dict = {1: "1", 2: "2", 3: "3"}
>>> reversed(dict)
<dict_reversekeyiterator object at 0x7f72ca795130>

Bu cevap, diğer cevaplar, yorumlar veya sorunun kendisi tarafından kapsanmayan yeni bir şey içeriyor mu?
normanius

@normanius lil görsel kod örneği var, hızlı tarayıcı için yararlı olabilir
jamylak
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.