Python sözlüğü bir karma tablo örneği mi?


187

Python'daki temel veri yapılarından biri, herhangi bir türdeki "değerleri" aramak için "anahtarları" kaydetmeye izin veren sözlüktür. Bu, dahili olarak karma tablo olarak uygulandı mı? Eğer değilse, nedir?


2
Teknik ayrıntılarla ilgileniyorsanız, Beautiful Code'daki bir makale Python'un dictuygulamasının iç kısımlarıyla ilgilidir .
Torsten Marek

Bu, Beautiful Code'daki en sevdiğim bölümlerden biriydi.
DGentry

4
Brandon Craig Rhodes'ın python sözlüğünün nasıl çalıştığını tartışan bir konuşma, youtube.com/watch?v=C4Kc8xzcA68 .
chandola

Bellek ve CPython'da uygulamayı açığa çıkaran bir süreliğine bir diksiyon gösteren bir diyagram aradım. Kitaba referans verdiğiniz için teşekkür ederiz!
Chen

Yanıtlar:


241

Evet, bir karma eşleme veya karma tablosu. Tim Peters tarafından yazılmış gibi, Python en dict uygulamasının tarifi okuyabilir burada .

Bu nedenle, 'kilitlenemez' bir şeyi bir liste anahtarı olarak, bir liste gibi kullanamazsınız:

>>> a = {}
>>> b = ['some', 'list']
>>> hash(b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list objects are unhashable
>>> a[b] = 'some'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: list objects are unhashable

Sen edebilirsiniz karma tablolar hakkında daha fazla okumak veya bu python nasıl uygulandığını kontrol ve o şekilde uygulandığına, niçin .


1
Tim Peters bağlantı dikişleri kırılacak, orada temiz bir bağlantı var mı?
Matt Alcock

1
@MattAlcock: Bağlantıyı güncelledim. Bazen (genellikle e-posta adreslerinin bir yere kaldırılmasını isteyen biri nedeniyle) python listesi arşivleri yeniden oluşturulur ve e-postaların kimlikleri değişir, böylece bu bağlantılar kesilir. Pydotorg yöneticileri genellikle bundan kaçınmaya çalışırlar.
Martijn Pieters

Ancak kullanarak .keys()bir anahtar listesi alabilirsiniz. Gerçek bir karma tablo anahtarları depolamaz, sadece yerden tasarruf etmek için karma yapar.
noɥʇʎԀʎzɐɹƆ

Python dict uygulamasının daha ayrıntılı açıklaması burada: laurentluce.com/posts/python-dictionary-implementation
Daniel Goldfarb

@ noɥʇʎԀʎzɐɹƆ - anahtarın kendisi saklanmaz, sadece ona ve karmaya referans verilir.
nosklo

32

Bir Python sözlüğünde, hash () tablosundaki bir tablo aramasından daha fazlası olmalıdır. Kaba deneylerle bu karma çarpışmayı buldum :

>>> hash(1.1)
2040142438
>>> hash(4504.1)
2040142438

Yine de sözlüğü kırmaz:

>>> d = { 1.1: 'a', 4504.1: 'b' }
>>> d[1.1]
'a'
>>> d[4504.1]
'b'

Aklı kontrol:

>>> for k,v in d.items(): print(hash(k))
2040142438
2040142438

Muhtemelen hash () işlevinin ötesinde, sözlük anahtarları arasındaki çarpışmaları önleyen başka bir arama düzeyi daha vardır. Ya da belki dict () farklı bir karma kullanır.

(Bu arada, bu Python 2.7.10'da. Python 3.4.3 ve 3.5.0'da bir çarpışma ile aynı hikaye hash(1.1) == hash(214748749.8).)


14
Dolayısıyla çarpışmalar kaçınılmazdır. Set S, sonsuz sayıda öğe içerebilir ve bunun bir bilgisayarın depolayabileceği bir sayıya hash olmasını istersiniz. Bir karma tablosunun her kullanılabilir uygulaması, en sık kullanılan yöntemlerden ikisi a) açık adresleme ve b) zincirleme olmak üzere çarpışmaları çözer. Mükemmel bir karma kullanmaması, bir karma tablo olmadığı anlamına gelmez.
TurnipEntropy

1
Çarpışmalar genellikle gerçekleşecektir, çünkü sonsuz olası yıkanabilir değerler ve sonlu karma kodlar vardır. Bir karma tablo bile çarpışmayı bir şekilde ele almak zorunda kalacaktı.
Yanfeng Liu

3
@YanfengLiu Bunların TurnipEntropy ile tam olarak aynı puan olduğuna inanıyorum.
Bob Stein

1
Python 3.7'de, aslında 2E20 eksi 1 olası hash değeri var gibi görünüyor. -1E20 eksi 1 - (+) 1E20 eksi 1. Deneyin hash('I wandered lonely as a cloud, that drifts on high o\'er vales and hills, when all at once, I saw a crowd, a host of golden daffodils.')Bu, 19 basamaklı bir ondalık sayı verir - -4037225020714749784eğer bakım için yeterince inek iseniz. Kendi kelimelerinizle devam edin, çocuklar ve hash hala 19 haneli bir sayı. Ben Python karma olabilir dize uzunluğu bir sınırı olduğunu varsayalım, ancak olası değerlerden çok daha olası dizeleri söylemek güvenli. Ve hash(False)bu arada = 0.
Croxford

22

Evet. Dahili olarak Z / 2 ( kaynak ) üzerinde ilkel bir polinom temel alınarak açık karma olarak uygulanır .


7

Nosklo'nun açıklamasını genişletmek için:

a = {}
b = ['some', 'list']
a[b] = 'some' # this won't work
a[tuple(b)] = 'some' # this will, same as a['some', 'list']
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.