2008-09-22 43 views
126

Một trong những cấu trúc dữ liệu cơ bản trong Python là từ điển, cho phép người ta ghi lại "các khóa" để tra cứu "các giá trị" của bất kỳ loại nào. Điều này có được thực thi nội bộ dưới dạng bảng băm không? Nếu không, nó là gì?Từ điển Python có phải là một ví dụ về bảng băm không?

+1

Dưới đây là một cuộc nói chuyện bởi Brandon Craig Rhodes thảo luận về cách điển python công trình , https://www.youtube.com/watch?v=C4Kc8xzcA68. – chandola

Trả lời

174

Vâng, đó là bản đồ băm hoặc bảng băm. Bạn có thể đọc mô tả về triển khai dict của python, được viết bởi Tim Peters, here.

Đó là lý do tại sao bạn không thể sử dụng một cái gì đó 'không hashable' như một chìa khóa dict, giống như một danh sách:

>>> 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 

Bạn có thể read more about hash tables hoặc check how it has been implemented in pythonwhy it is implemented that way.

+1

Các đường nối liên kết Tim Peters bị hỏng, có liên kết rõ ràng không? –

+1

@MattAlcock: Tôi đã cập nhật liên kết. Đôi khi (thường là do ai đó muốn địa chỉ email của họ bị xóa ở đâu đó) danh sách lưu trữ python được xây dựng lại và id của email thay đổi, do đó phá vỡ các liên kết này. Các quản trị viên pydotorg thường cố gắng tránh những ngày này. –

+0

Nhưng sử dụng '.keys()' có thể lấy danh sách các phím. Một bảng băm thực sự sẽ không lưu trữ khóa, chỉ cần băm để tiết kiệm không gian. –

17

Có. Bên trong nó được thực hiện như băm mở dựa trên đa thức nguyên thủy trên Z/2 (source).

29

Nếu bạn quan tâm đến chi tiết kỹ thuật, một bài viết trong số Beautiful Code sẽ đề cập đến nội dung thực thi dict của Python.

+1

Đó là một trong những chương yêu thích của tôi trong Bộ luật đẹp. – DGentry

5

Để mở rộng khi giải thích nosklo của:

a = {} 
b = ['some', 'list'] 
a[b] = 'some' # this won't work 
a[tuple(b)] = 'some' # this will, same as a['some', 'list'] 
11

Phải có hơn một từ điển Python hơn một tra cứu bảng trên băm(). Bằng cách thử nghiệm vũ phu tôi thấy băm này va chạm:

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

Tuy nhiên, nó không phá vỡ các từ điển:

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

Sanity kiểm tra:

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

Có thể có một mức tham chiếu sau hash() giúp tránh va chạm giữa các khóa từ điển. Hoặc có thể dict() sử dụng một băm khác nhau.

(By the way, đây bằng Python 2.7.10. Tương tự câu chuyện bằng Python 3.4.3 và 3.5.0 với một vụ va chạm tại hash(1.1) == hash(214748749.8).)

+3

Nó có giải pháp cho các va chạm. –

+0

Nó sử dụng '__eq__' để giải quyết xung đột. – dmitry

+2

Vì vậy, va chạm là không thể tránh khỏi. Bộ S có thể chứa một số lượng lớn các mục và bạn muốn nó băm thành một số mà một máy tính có thể lưu trữ. Mỗi thực thi có thể sử dụng của một bảng băm giải quyết xung đột, với hai phương pháp thường xuyên nhất là a) mở địa chỉ và b) chuỗi. Chỉ vì nó không sử dụng một băm hoàn hảo không có nghĩa là nó không phải là một bảng băm. – TurnipEntropy

Các vấn đề liên quan