Là ngôn ngữ lập trình có mục đích chung, Python cung cấp nhiều loại dữ liệu tích hợp sẵn cho các trường hợp sử dụng khác nhau
Khi bạn học những điều cơ bản này, có lẽ bạn đã gặp phải đề cập đến hashable tại một số điểm nhất định. Ví dụ: bạn có thể thấy rằng các khóa trong dict
cần có thể băm được [xem một ví dụ nhỏ trong đoạn mã bên dưới]
Ví dụ khác, có đề cập rằng các phần tử trong set
cần phải được băm
Bạn có thể thắc mắc — Hashable chính xác có nghĩa là gì? . Nhiều câu hỏi liên quan có thể được hỏi
Trong bài viết này, chúng ta sẽ xem xét một số điểm chính về khả năng băm để bạn có thể tìm hiểu cách giải quyết những câu hỏi này. Cuối cùng, bạn có thể sẽ phát hiện ra rằng những câu hỏi này thực ra không khó chút nào, không giống như những gì bạn có thể nghĩ ban đầu.
Đối tượng nào có thể băm được và đối tượng nào không?
Trước khi chúng tôi bắt đầu bất kỳ lời giải thích cơ học nào, câu hỏi đầu tiên mà chúng tôi muốn giải quyết là đối tượng nào có thể băm được và đối tượng nào không.
Bởi vì chúng ta biết rằng Python yêu cầu rõ ràng rằng các phần tử trong một set
phải có thể băm được, nên chúng ta có thể kiểm tra khả năng băm của một đối tượng bằng cách đơn giản là thử thêm đối tượng vào một set
. Chèn thành công cho biết các đối tượng có thể băm và ngược lại
>>> # Create an empty set object
>>> elements = set[]
>>>
>>> # The list of objects with each to be inserted to the set
>>> items = [1, 0.1, 'ab', [2, 3], {'a': 1}, [1, 2], {2, 4}, None]
Như trong đoạn mã trên, tôi đã tạo một biến set
có tên là elements
và một biến list
có tên là items
, bao gồm các loại dữ liệu dựng sẵn được sử dụng phổ biến nhất. int
, dict
0, dict
1, dict
2, dict
, list
, set
, và dict
6
Thử nghiệm mà tôi sẽ thực hiện là thêm mỗi ________ 8 vào ________ 6. Tôi sẽ không sử dụng vòng lặp dict
9 trong trường hợp này, bởi vì bất kỳ set
0 nào có thể xảy ra sẽ dừng quá trình lặp lại. Thay vào đó, tôi sẽ chỉ truy xuất các mục riêng lẻ bằng cách lập chỉ mục
Như bạn có thể thấy trong đoạn mã trên, đây là tóm tắt nhanh về kết quả của thử nghiệm
Trả lời câu hỏi của phần
- Các loại dữ liệu có thể băm.
int
,dict
0,dict
1,dict
2 vàdict
6 - Các kiểu dữ liệu không thể sửa đổi.
dict
,list
vàset
Nếu bạn hoàn toàn mới lập trình Python, bạn có thể nhận thấy rằng ba loại dữ liệu không thể băm này đều có thể thay đổi về bản chất, trong khi năm loại dữ liệu có thể băm này đều là bất biến
Về bản chất, các dữ liệu có thể thay đổi này là các đối tượng có thể thay đổi giá trị sau khi tạo, trong khi giá trị của các đối tượng không thể thay đổi không thể thay đổi sau khi tạo
Khả năng thay đổi dữ liệu là một chủ đề độc lập mà tôi đã đề cập trước đây trong bài viết khác của mình
Hashable nghĩa là gì?
Bây giờ bạn có một số ý tưởng về đối tượng nào có thể băm được và đối tượng nào không, nhưng chính xác thì hàm băm có nghĩa là gì?
Trên thực tế, bạn có thể đã nghe nhiều thuật ngữ máy tính tương tự liên quan đến hashable, chẳng hạn như hash value, hashing, hash table và hashmap. Về cốt lõi, chúng chia sẻ cùng một quy trình cơ bản - băm
Quá trình băm chung [Wikipedia, Miền công cộng]
Sơ đồ trên cho bạn thấy quá trình băm chung. Chúng tôi bắt đầu với một số giá trị dữ liệu thô [được gọi là khóa trong hình]
Hàm băm, đôi khi được gọi là hàm băm, sẽ thực hiện các tính toán cụ thể và xuất các giá trị băm [được gọi là hàm băm trong hình] cho các giá trị dữ liệu thô
Băm và các khái niệm liên quan của nó cần cả một cuốn sách để làm rõ, điều này nằm ngoài phạm vi của bài viết hiện tại. Tuy nhiên, một số khía cạnh quan trọng đã được thảo luận ngắn gọn trong bài viết trước của tôi
Ở đây, tôi sẽ chỉ nhấn mạnh một số điểm chính có liên quan đến cuộc thảo luận hiện tại
- Hàm băm phải mạnh mẽ về mặt tính toán sao cho các đối tượng khác nhau sẽ có các giá trị băm khác nhau. Khi các đối tượng khác nhau có cùng giá trị băm, xung đột sẽ xảy ra [như trong hình trên] và cần được xử lý
- Hàm băm phải nhất quán sao cho các đối tượng giống nhau sẽ luôn dẫn đến các giá trị băm giống nhau
Python đã triển khai hàm băm tích hợp để tạo ra các giá trị băm cho các đối tượng của nó. Cụ thể, chúng ta có thể truy xuất giá trị băm của một đối tượng bằng cách sử dụng hàm set
9 tích hợp. Đoạn mã sau đây cho bạn thấy một số ví dụ
Như được hiển thị ở trên, chúng tôi có thể nhận được các giá trị băm - số nguyên cho các đối tượng_______9 và dict
2
Tuy nhiên, cả đối tượng list
và đối tượng dict
đều không có giá trị băm. Những kết quả này phù hợp với sự khác biệt mà chúng tôi đang thực hiện giữa các đối tượng có thể băm và không thể băm trong phần trước
Trả lời câu hỏi của phần
- Có thể băm. Một đặc điểm của đối tượng Python để cho biết liệu đối tượng có giá trị băm hay không, cho phép đối tượng đóng vai trò là khóa trong từ điển hoặc thành phần trong tập hợp
Làm cách nào chúng ta có thể tùy chỉnh khả năng băm?
Tính linh hoạt của Python với tư cách là ngôn ngữ lập trình đa năng chủ yếu đến từ việc hỗ trợ tạo các lớp tùy chỉnh. Với các lớp của riêng bạn, nhiều dữ liệu và hoạt động liên quan có thể được nhóm theo cách dễ đọc và có ý nghĩa hơn nhiều
Điều quan trọng là Python đã phát triển đủ thông minh để làm cho các đối tượng tùy chỉnh của chúng ta có thể băm được theo mặc định trong hầu hết các trường hợp
Xem xét ví dụ sau. Chúng tôi đã tạo một lớp tùy chỉnh, set
4, cho phép chúng tôi tạo các phiên bản bằng cách chỉ định tên và số an sinh xã hội của một người
Đáng chú ý, chúng tôi đã ghi đè hàm set
5 mặc định bằng phương pháp f-string, điều này sẽ cho phép chúng tôi hiển thị đối tượng với thông tin dễ đọc hơn, như được hiển thị trong dòng cuối cùng của đoạn mã
Như được hiển thị trong đoạn mã trên, chúng ta có thể tìm ra giá trị băm cho đối tượng đã tạo set
6 bằng cách sử dụng hàm set
9 tích hợp. Điều quan trọng là chúng ta có thể bao gồm đối tượng set
6 như một thành phần trong đối tượng set
, điều này thật tốt
Tuy nhiên, điều gì sẽ xảy ra nếu chúng ta muốn thêm nhiều trường hợp set
4 vào tập hợp?
Xem đoạn mã sau. Tôi đã tạo một phiên bản set
4 khác, set
4, có cùng tên và số an sinh xã hội — về cơ bản là cùng một thể nhân
Tuy nhiên, khi chúng tôi thêm người này vào đối tượng set
, set
6, cả hai đối tượng set
4 đều ở trong set
, điều mà chúng tôi không muốn xảy ra
Bởi vì, theo thiết kế, chúng tôi muốn đối tượng set
lưu trữ những thể nhân duy nhất. Phù hợp với cả hai người được bao gồm trong đối tượng set
, chúng tôi phát hiện ra rằng hai trường hợp set
4 này thực sự khác nhau
Tôi sẽ chỉ cho bạn mã về cách chúng tôi có thể làm cho lớp tùy chỉnh set
4 thông minh hơn để nó biết những người nào giống hoặc khác nhau, về vấn đề đó
Trong đoạn mã trên, chúng tôi đã cập nhật lớp tùy chỉnh set
4 bằng cách ghi đè các hàm set
4 và set
5
Trước đây chúng tôi đã đề cập rằng hàm set
6 được sử dụng để tính giá trị băm của một đối tượng. Hàm set
7 được sử dụng để so sánh đối tượng này với đối tượng khác cho bằng nhau và nó cũng yêu cầu các đối tượng so sánh bằng nhau phải có cùng giá trị băm
Theo mặc định, các thể hiện của lớp tùy chỉnh được so sánh bằng cách so sánh danh tính của chúng bằng cách sử dụng hàm set
8 tích hợp [tìm hiểu thêm về hàm set
8 bằng cách tham khảo bài viết này]
Với cách triển khai được cập nhật, chúng ta có thể thấy rằng khi chúng ta cố gắng tạo một đối tượng set
bao gồm hai đối tượng set
4, hàm set
6 được gọi sao cho đối tượng đã đặt chỉ giữ các đối tượng có giá trị băm duy nhất
Một điều khác cần lưu ý là khi Python kiểm tra xem các phần tử trong đối tượng set
có giá trị băm duy nhất hay không, nó sẽ đảm bảo rằng các đối tượng này cũng không bằng nhau bằng cách gọi hàm set
7
Trả lời câu hỏi của phần
tùy biến. Để cung cấp các hành vi tùy chỉnh về khả năng băm và bình đẳng, chúng tôi cần triển khai các hàm set
4 và set
5 trong các lớp tùy chỉnh của mình
Phần kết luận
Trong bài viết này, chúng ta đã xem xét các khái niệm về hashable/hashability trong Python
Cụ thể, bằng cách giải quyết ba câu hỏi quan trọng, tôi hy vọng rằng bạn hiểu rõ hơn về khả năng băm trong Python. Khi có thể áp dụng, bạn có thể triển khai các hành vi khả năng băm phù hợp cho các lớp tùy chỉnh của riêng mình