Tôi đã thử tìm kiếm trên internet nhưng không thể tìm thấy ý nghĩa của hashable.
Khi họ nói các đối tượng là gì hashable
hoặc hashable objects
nó có nghĩa là gì?
Tôi đã thử tìm kiếm trên internet nhưng không thể tìm thấy ý nghĩa của hashable.
Khi họ nói các đối tượng là gì hashable
hoặc hashable objects
nó có nghĩa là gì?
Câu trả lời:
Từ bảng chú giải Python :
Một đối tượng có thể băm nếu nó có giá trị băm không bao giờ thay đổi trong suốt vòng đời của nó (nó cần một
__hash__()
phương thức) và có thể so sánh với các đối tượng khác (nó cần một phương thức__eq__()
hoặc__cmp__()
phương thức). Các đối tượng có thể băm so sánh bằng nhau phải có cùng giá trị băm.Hashability làm cho một đối tượng có thể sử dụng như một khóa từ điển và một thành viên được thiết lập, bởi vì các cấu trúc dữ liệu này sử dụng giá trị băm bên trong.
Tất cả các đối tượng tích hợp bất biến của Python đều có thể băm được, trong khi không có thùng chứa có thể thay đổi nào (như danh sách hoặc từ điển). Các đối tượng là các thể hiện của các lớp do người dùng định nghĩa có thể được băm theo mặc định; tất cả đều so sánh không bằng nhau và giá trị băm của chúng là của chúng
id()
.
hash value
bây giờ nó có giá trị băm là gì. bạn có thể đưa ra một số ví dụ
__hash__()
. Tổng quát hơn, xem en.wikipedia.org/wiki/Hash_feft
id(object)
là 16 lần kết quả của object.__hash__()
. Vì vậy, đoạn trích chú giải không chính xác cho phiên bản này - giá trị băm thì không id()
, nhưng nó được lấy từ nó (như thực sự được ghi chú trong các tài liệu cập nhật cho python 2.7.12).
hash((1, [2, 3]))
nhìn nó trong hành động. Tôi đã đăng một yêu cầu để sửa mục chú giải cho hashable.
Tất cả các câu trả lời ở đây đều có giải thích hoạt động tốt về các đối tượng có thể băm trong python, nhưng tôi tin rằng người ta cần hiểu thuật ngữ Hashing trước tiên.
Băm là một khái niệm trong khoa học máy tính được sử dụng để tạo ra các cấu trúc dữ liệu truy cập ngẫu nhiên, giả ngẫu nhiên, trong đó một lượng lớn dữ liệu sẽ được lưu trữ và truy cập nhanh chóng.
Ví dụ: nếu bạn có 10.000 số điện thoại và bạn muốn lưu trữ chúng trong một mảng (là cấu trúc dữ liệu tuần tự lưu trữ dữ liệu ở các vị trí bộ nhớ liền kề và cung cấp quyền truy cập ngẫu nhiên), nhưng bạn có thể không có lượng tiếp giáp cần thiết vị trí bộ nhớ.
Vì vậy, thay vào đó, bạn có thể sử dụng một mảng có kích thước 100 và sử dụng hàm băm để ánh xạ một tập hợp các giá trị vào cùng các chỉ mục và các giá trị này có thể được lưu trữ trong danh sách được liên kết. Điều này cung cấp một hiệu suất tương tự như một mảng.
Bây giờ, một hàm băm có thể đơn giản như chia số với kích thước của mảng và lấy phần còn lại làm chỉ mục.
Để biết thêm chi tiết, tham khảo https://en.wikipedia.org/wiki/Hash_feft
Dưới đây là một tài liệu tham khảo tốt khác: http://interactivepython.org/runestone/static/pythonds/SortSearch/Hashing.html
Bất cứ điều gì không thể thay đổi (phương tiện có thể thay đổi, có khả năng thay đổi) đều có thể được băm. Ngoài hàm băm cần tìm, nếu một lớp có nó, ví dụ. dir(tuple)
và tìm kiếm __hash__
phương pháp, đây là một số ví dụ
#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
Danh sách các loại bất biến:
int, float, decimal, complex, bool, string, tuple, range, frozenset, bytes
Danh sách các loại đột biến:
list, dict, set, bytearray, user-defined classes
Ellipsis
cũng là một loại không thay đổi và có thể được sử dụng làm chìa khóa cho a dict
.
hash(MyClass)
__hash__
và __eq__
. Hơn nữa, tất cả các lớp do người dùng định nghĩa đều thực hiện các phương thức này (và do đó có thể băm được), bởi vì chúng kế thừa các phương thức từ object
(lớp cơ sở phổ quát).
Theo cách hiểu của tôi theo thuật ngữ Python, khi bạn tạo một thể hiện của các đối tượng có thể băm, một giá trị không thể thay đổi cũng được tính theo các thành viên hoặc giá trị của thể hiện. Ví dụ: giá trị đó sau đó có thể được sử dụng làm khóa trong một lệnh như sau:
>>> 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'
chúng ta có thể thấy rằng giá trị băm của tuple_a và tuple_c là như nhau vì chúng có cùng các thành viên. Khi chúng ta sử dụng tuple_a làm khóa trong dict_a, chúng ta có thể thấy rằng giá trị của dict_a [tuple_c] là như nhau, có nghĩa là, khi chúng được sử dụng làm khóa trong một dict, chúng trả về cùng một giá trị vì các giá trị băm là giống nhau. Đối với những đối tượng không thể băm, hàm băm phương thức được định nghĩa là Không có:
>>> type(dict.__hash__)
<class 'NoneType'>
Tôi đoán giá trị băm này được tính dựa trên việc khởi tạo thể hiện, không phải theo cách động, đó là lý do tại sao chỉ các đối tượng bất biến là có thể băm. Hi vọng điêu nay co ich.
Hãy để tôi cho bạn một ví dụ hoạt động để hiểu các đối tượng có thể băm trong python. Tôi đang lấy 2 Tuples cho ví dụ này. Mỗi giá trị trong một tuple có Giá trị Hash duy nhất không bao giờ thay đổi trong suốt vòng đời của nó. Vì vậy, dựa trên điều này có giá trị, việc so sánh giữa hai bộ dữ liệu được thực hiện. Chúng ta có thể nhận giá trị băm của một phần tử tuple bằng cách sử dụng Id ().
Trong python, điều đó có nghĩa là đối tượng có thể là thành viên của các tập hợp để trả về một chỉ mục. Đó là, họ có danh tính / id duy nhất.
ví dụ: trong python 3.3:
cấu trúc dữ liệu Danh sách không thể băm được nhưng cấu trúc dữ liệu Tuples có thể băm được.
id
, đó là (xấp xỉ) địa chỉ của đối tượng trong bộ nhớ.
Hashable = có khả năng được băm.
Ok, băm là gì? Hàm băm là một hàm lấy một đối tượng, giả sử một chuỗi như Python Python, 'và trả về mã có kích thước cố định. Để đơn giản, giả sử giá trị trả về là một số nguyên.
Khi tôi chạy hàm băm ('Python') trong Python 3, tôi nhận được 5952713340227947791. Các phiên bản khác nhau của Python được tự do thay đổi hàm băm cơ bản, do đó bạn có thể sẽ nhận được một giá trị khác. Điều quan trọng là cho dù bây giờ nhiều lần tôi chạy hàm băm ('Python'), tôi sẽ luôn nhận được kết quả tương tự với cùng một phiên bản Python.
Nhưng hàm băm ('Java') trả về 1753925553814008565. Vì vậy, nếu đối tượng tôi đang băm thay đổi, kết quả cũng vậy. Mặt khác, nếu đối tượng tôi đang băm không thay đổi, thì kết quả vẫn giữ nguyên.
Vì sao vấn đề này?
Vâng, ví dụ, từ điển Python yêu cầu các khóa là bất biến. Đó là, các khóa phải là các đối tượng không thay đổi. Chuỗi là bất biến trong Python, cũng như các loại cơ bản khác (int, float, bool). Tuples và fro chục cũng là bất biến. Danh sách, mặt khác, không phải là bất biến (nghĩa là chúng có thể thay đổi) bởi vì bạn có thể thay đổi chúng. Tương tự, dicts là đột biến.
Vì vậy, khi chúng tôi nói một cái gì đó có thể băm, chúng tôi có nghĩa là nó là bất biến. Nếu tôi cố gắng chuyển một loại có thể thay đổi cho hàm hash (), nó sẽ thất bại:
>>> 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
Trong Python, bất kỳ đối tượng bất biến nào (như số nguyên, boolean, chuỗi, tuple) đều có thể băm, có nghĩa là giá trị của nó không thay đổi trong suốt vòng đời của nó. Điều này cho phép Python tạo một giá trị băm duy nhất để xác định nó, có thể được sử dụng bởi các từ điển để theo dõi các khóa và bộ duy nhất để theo dõi các giá trị duy nhất.
Đây là lý do tại sao Python yêu cầu chúng ta sử dụng các kiểu dữ liệu bất biến cho các khóa trong từ điển.
Để tạo bảng băm từ đầu, tất cả các giá trị phải được đặt thành "Không" và được sửa đổi khi có yêu cầu. Các đối tượng có thể băm tham chiếu đến các kiểu dữ liệu có thể sửa đổi (Từ điển, danh sách, v.v.). Mặt khác, các bộ không thể được khởi tạo lại sau khi được gán, vì vậy các bộ không thể băm được. Trong khi đó, biến thể của tập hợp () - froundredet () - có thể băm được.
__hash__()
phương pháp .