Apa yang harus saya lakukan untuk menggunakan objek saya dari jenis khusus sebagai kunci dalam kamus Python (di mana saya tidak ingin "objek id" untuk bertindak sebagai kunci), misalnya
class MyThing:
def __init__(self,name,location,length):
self.name = name
self.location = location
self.length = length
Saya ingin menggunakan MyThing's sebagai kunci yang dianggap sama jika nama dan lokasinya sama. Dari C # / Java saya terbiasa harus menimpa dan memberikan metode kode hash dan sama, dan berjanji untuk tidak bermutasi apa pun tergantung kode hash.
Apa yang harus saya lakukan dengan Python untuk mencapai ini? Haruskah saya meratakan?
(Dalam kasus sederhana, seperti di sini, mungkin akan lebih baik untuk menempatkan tuple (nama, lokasi) sebagai kunci - tetapi pertimbangkan saya ingin kunci menjadi objek)
python
dictionary
Orang dgn nama yg tdk dikenal
sumber
sumber
MyThing
, jika mereka memiliki yang samaname
danlocation
, untuk mengindeks kamus untuk mengembalikan nilai yang sama, bahkan jika mereka dibuat secara terpisah sebagai dua "objek" yang berbeda.Jawaban:
Anda perlu menambahkan 2 metode , perhatikan
__hash__
dan__eq__
:Dokumentasi dict Python mendefinisikan persyaratan ini pada objek kunci, yaitu mereka harus hashable .
sumber
hash(self.name)
terlihat lebih bagus daripadaself.name.__hash__()
, dan jika Anda melakukannya dan Anda bisa lakukanhash((x, y))
untuk menghindari XORing sendiri.x.__hash__()
seperti itu juga salah , karena dapat menghasilkan hasil yang salah : pastebin.com/C9fSH7eFand
untuk__eq__
tetapi kemudian saya berpikir "mengapa tidak menggunakan tuple?" karena saya sering melakukan itu (saya pikir itu lebih mudah dibaca). Untuk beberapa alasan aneh, mataku tidak kembali mempertanyakan__hash__
.__ne__()
telah "diperbaiki" .Alternatif dengan Python 2.6 atau di atas adalah menggunakan
collections.namedtuple()
- menghemat Anda menulis metode khusus:sumber
Anda menimpa
__hash__
jika Anda menginginkan semantik-hash khusus, dan__cmp__
atau__eq__
agar kelas Anda dapat digunakan sebagai kunci. Objek yang membandingkan kebutuhan yang sama untuk memiliki nilai hash yang sama.Python mengharapkan
__hash__
untuk mengembalikan integer, pengembalianBanana()
tidak dianjurkan :)Kelas yang ditentukan pengguna
__hash__
secara default memanggilid(self)
, seperti yang Anda catat.Ada beberapa tips tambahan dari dokumentasi :
sumber
__eq__
atau__cmp__
.__cmp__
diberikan kepada Anda oleh Python jika itu adalah kelas yang ditentukan pengguna, tetapi Anda mungkin ingin tetap menimpanya untuk mengakomodasi semantik baru.cmp
dan menggunakan=
pada kelas pengguna yang tidak mengesampingkan metode ini, salah satunya harus diterapkan untuk memenuhi persyaratan penanya bahwa instance dengan nama dan lokasi yang sama memiliki kunci kamus yang sama.