Python'da “yıkanabilir” ne demektir?


194

İnternette arama yapmayı denedim ama yıkanabilir anlamını bulamadım.

Nesneler olduğunu söylediklerinde hashableveya hashable objectsne anlama geliyor?



5
kullanılabilir nesneleri veya başka bir şeyi arar, ancak bağlantıların hiçbiri yıkanabilirliğin gerçekte ne anlama geldiğini açıklamaz
user1755071

Yanıtlar:


181

Gönderen Python sözlüğü :

Bir nesne, kullanım ömrü boyunca hiçbir zaman değişmeyen bir karma değere sahipse (bir __hash__()yönteme ihtiyaç duyar ) ve diğer nesnelerle karşılaştırılabilecekse ( __eq__()veya bir __cmp__()yönteme ihtiyaç duyarsa) yıkanabilir . Eşit karşılaştırılabilen yıkanabilir nesneler aynı karma değerine sahip olmalıdır.

Hashability, bir nesneyi sözlük anahtarı ve küme üyesi olarak kullanılabilir hale getirir, çünkü bu veri yapıları karma değerini dahili olarak kullanır.

Python'un değişmez yerleşik nesnelerinin tümü yıkanabilirken, değiştirilebilir kaplar (listeler veya sözlükler gibi) yoktur. Kullanıcı tanımlı sınıfların örnekleri olan nesneler varsayılan olarak yıkanabilir; hepsi eşitsiz karşılaştırırlar ve karma değerleri onlarındır id().


2
eğer hash valueşimdi karma değeri nedir? biraz örnek verebilir misiniz
user1755071 26:13

2
@ user55711: Burada karma değeri çağrının sonucudur __hash__(). Daha genel olarak, bkz. En.wikipedia.org/wiki/Hash_function
NPE

16
@TorstenBronger: Çünkü iki eşit olmayan nesne aynı değere hash edebilir. Başka bir deyişle, hash kayıplıdır.
NPE

1
Python-2.7.12'de sonucu id(object)16x sonucudur object.__hash__(). Bu nedenle sözlük alıntısı bu sürüm için yanlış - karma değeri değil id(), ancak bundan türetilmiştir (gerçekten de piton 2.7.12 için güncellenmiş dokümanlarda belirtildiği gibi).
davidA

2
Bu eski bir yazı olduğunu biliyorum, ama burada kopyalanan sözlük girişinin tamamen doğru olmadığını belirtmek gerekir. Bir grubun içine değiştirilebilir bir nesne (liste gibi) koyabilirsiniz. Demet hala değişmez, ancak içindeki listeyi değiştirebilirsiniz, bu yüzden yıkanamaz. hash((1, [2, 3]))Eylem halinde görmeye çalışın . Yıkanabilir terimler sözlüğü girişini düzeltmek için bir istek gönderdim.
John Riehl

102

Buradaki tüm cevapların python'da yıkanabilir nesnelerin iyi çalışma açıklaması var, ama önce Hashing terimini anlamamız gerektiğine inanıyorum.

Hashing , büyük miktarda verinin hızlı bir şekilde depolanacağı ve erişileceği yüksek performanslı, sahte rasgele erişim veri yapıları oluşturmak için kullanılan bir bilgisayar bilimidir.

Örneğin, 10.000 telefon numaranız varsa ve bunları bir dizide saklamak istiyorsanız (bu, verileri bitişik bellek konumlarında depolayan ve rasgele erişim sağlayan sıralı bir veri yapısıdır), ancak gerekli miktarda bitişik olmayabilir bellek konumları.

Bu nedenle, bunun yerine 100 boyutlu bir dizi kullanabilir ve bir değer kümesini aynı indekslerle eşlemek için bir karma işlevi kullanabilirsiniz ve bu değerler bağlantılı bir listede saklanabilir. Bu, bir diziye benzer bir performans sağlar.

Şimdi, bir karma işlevi, sayıyı dizinin boyutuna bölmek ve geri kalanını dizin olarak almak kadar basit olabilir.

Daha fazla ayrıntı için bkz. Https://en.wikipedia.org/wiki/Hash_function

İşte başka bir iyi referans: http://interactivepython.org/runestone/static/pythonds/SortSearch/Hashing.html


1
Bu, karma konusunda ilginç bir bakış açısı. Ben öyle düşünmemiştim.
yuvgin

@yuvgin hash tabloları genellikle seyrek dizileri uygulamak için kullanılır (yani burada verilen örnek).
Eli Korvigo

@EliKorvigo Normal dizileri bir karma tablonun son derece optimize edilmiş sürümleri olarak düşünmeyi seviyorum.
Mark Ransom

1
karma kavramını netleştirmek için telefon numarası dizi senaryosu ile ilgili basit bir kod üretebilir misiniz?
Istiaque Ahmed

18

Değişken olmayan her şey (değişebilir olasılıklar, değişmesi muhtemel) hashed edilebilir. Yanında hash fonksiyonunun yanı sıra, eğer bir sınıf varsa, örn. dir(tuple)ve __hash__yöntemi ararken , işte bazı örnekler

#x = hash(set([1,2])) #set unhashable
x = hash(frozenset([1,2])) #hashable
#x = hash(([1,2], [2,3])) #tuple of mutable objects, unhashable
x = hash((1,2,3)) #tuple of immutable objects, hashable
#x = hash()
#x = hash({1,2}) #list of mutable objects, unhashable
#x = hash([1,2,3]) #list of immutable objects, unhashable

Değişmez tiplerin listesi:

int, float, decimal, complex, bool, string, tuple, range, frozenset, bytes

Değişken tiplerinin listesi:

list, dict, set, bytearray, user-defined classes

Son zamanlarda Ellipsisbunun da değişmez bir tip olduğunu ve a için bir anahtar olarak kullanılabileceğini öğrendim dict.
Gábor Fekete

Kullanıcı tanımlı sınıflar bile kullanılabilir ancak yalnızca adları örnek değildir. Örn:hash(MyClass)
Gábor Fekete

1
@ GáborFekete, kullanıcı tanımlı sınıfların örnekleri, sınıfları uygularsa __hash__ve __eq__. Dahası, kullanıcı tanımlı tüm sınıflar bu yöntemleri uygular (ve böylece yıkanabilir), çünkü yöntemleri object(evrensel temel sınıftan) miras alırlar .
Eli Korvigo

7

Python sözlüğüne göre anladığım kadarıyla, yıkanabilir nesnelerin bir örneğini oluşturduğunuzda, örneğin üyeleri veya değerlerine göre değiştirilemez bir değer de hesaplanır. Örneğin, bu değer aşağıdaki gibi bir dikte içinde bir anahtar olarak kullanılabilir:

>>> tuple_a = (1,2,3)
>>> tuple_a.__hash__()
2528502973977326415
>>> tuple_b = (2,3,4)
>>> tuple_b.__hash__()
3789705017596477050
>>> tuple_c = (1,2,3)
>>> tuple_c.__hash__()
2528502973977326415
>>> id(a) == id(c)  # a and c same object?
False
>>> a.__hash__() == c.__hash__()  # a and c same value?
True
>>> dict_a = {}
>>> dict_a[tuple_a] = 'hiahia'
>>> dict_a[tuple_c]
'hiahia'

tuple_a ve tuple_c hash değerlerinin aynı üyelere sahip oldukları için aynı olduğunu görebiliriz. Dict_a'daki anahtar olarak tuple_a kullandığımızda, dict_a [tuple_c] değerinin aynı olduğunu bulabiliriz, yani bir diktede anahtar olarak kullanıldıklarında, hash değerleri olduğu için aynı değeri döndürürler. aynısı. Yıkanamayan nesneler için, yöntem karması Yok olarak tanımlanır:

>>> type(dict.__hash__) 
<class 'NoneType'>

Bu karma değerin, dinamik bir şekilde değil, örneğin başlatılmasıyla hesaplandığını tahmin ediyorum, bu yüzden sadece değişmez nesneler yıkanabilir. Bu yardımcı olur umarım.


4

Python'daki yıkanabilir nesneleri anlamak için size çalışan bir örnek vereyim. Bu örnek için 2 Tuples alıyorum. Bir tuple içindeki her değer, ömrü boyunca asla değişmeyen benzersiz bir Hash Değerine sahiptir. Bu yüzden değere dayanarak, iki tuple arasındaki karşılaştırma yapılır. Id () kullanarak bir tuple elemanının hash değerini alabiliriz.

2 tuple karşılaştırması2 tuple arasındaki eşdeğerlik


26
bu bir görüntü yerine metin olarak daha yararlı olacaktır
baxx

7
bu yanlış bir cevap. id (), başvurulan adresi bir bellekte gösterir, bu bir karma değer değildir. Karma elde etmek için __hash __ () işlevini kullanın. ör .: t1 .__ hash __ ()
Vlad

@ascentman Yanlış olduğuna inandığınız bir yanıtı düzenlemekte tereddüt etmeyin. Yaptığınız düzenleme hakem değerlendirilir ve kabul edilirse küçük bir puan ödülü alırsınız.
XavierStuvw

4

Python'da, nesnenin bir dizin döndürmek için setlerin üyesi olabileceği anlamına gelir. Yani, benzersiz bir kimliği / kimliği var.

örneğin, python 3.3'te:

veri yapısı Listeler yıkanamaz, ancak veri yapısı Tuples yıkanabilir.


Karma, idbellekteki nesnenin adresi olan (yaklaşık olarak) ile aynı değildir .
poolie

3

Hashable = hash edilebilir.

Tamam, karma nedir? Karma işlevi, bir nesneyi, örneğin “Python” gibi bir dize alan ve sabit boyutlu bir kod döndüren bir işlevdir. Basit olması için, dönüş değerinin bir tam sayı olduğunu varsayalım.

Python 3'te karma ('Python') çalıştırdığımda sonuç olarak 5952713340227947791 alıyorum. Python'un farklı sürümleri temeldeki hash işlevini değiştirmekte özgürdür, bu nedenle muhtemelen farklı bir değer elde edersiniz. Önemli olan şu ki, artık birçok kez karma ('Python') çalıştırsam, her zaman aynı sonucu Python ile alacağım.

Ancak hash ('Java') 1753925553814008565 değerini döndürür. Dolayısıyla, karma yaptığım nesne değişirse, sonuç da değişir. Öte yandan, hash ettiğim nesne değişmezse, sonuç aynı kalır.

Bu neden önemli?

Örneğin, Python sözlükleri anahtarların değişmez olmasını gerektirir. Yani, anahtarlar değişmeyen nesneler olmalıdır. Dizeler, diğer temel tipler (int, float, bool) gibi Python'da değişmezdir. Tuples ve frozensets de değişmezdir. Öte yandan listeler değiştirilemez (yani değiştirilebilir), çünkü bunları değiştirebilirsiniz. Benzer şekilde, dikmeler değiştirilebilir.

Yani bir şeyin yıkanabilir olduğunu söylediğimizde, değişmez olduğunu kastediyoruz. Hash () işlevine değiştirilebilir bir tür iletmeye çalışırsam başarısız olur:

>>> hash('Python')
1687380313081734297
>>> hash('Java')
1753925553814008565
>>>
>>> hash([1, 2])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> hash({1, 2})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'
>>> hash({1 : 2})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>>
>>> hash(frozenset({1, 2}))
-1834016341293975159
>>> hash((1, 2))
3713081631934410656

1
Python'un her bir işlemin başlangıcında karma algoritmasını rastgele tohumladığını unutmayın. Bu nedenle, farklı işlemlerde iki kez karma ('Python') çalıştırırsanız aslında farklı karma değerleri alırsınız.
D Hudson

2

Python'da, herhangi bir değişmez nesne (bir tamsayı, boole, dize, tuple gibi) yıkanabilir, yani ömrü boyunca değeri değişmez. Bu, Python'un sözlükler tarafından benzersiz anahtarları izlemek için kullanılabileceği ve benzersiz değerleri izlemek için kümeler kullanabileceği benzersiz bir hash değeri oluşturmasına izin verir.

Bu yüzden Python sözlükteki anahtarlar için değiştirilemez veri tipleri kullanmamızı gerektirir.


-1

Bir karma tabloyu sıfırdan oluşturmak için, tüm değerlerin "Yok" olarak ayarlanması ve bir gereksinim ortaya çıktığında değiştirilmesi gerekir. Yıkanabilir nesneler değiştirilebilir veri tiplerini (Sözlük, listeler vb.) İfade eder. Öte yandan setler atandıktan sonra yeniden başlatılamaz, bu nedenle setler yıkanamaz. Oysa set () - frozenset () - varyantı yıkanabilir.

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.