Python có thể băm và không thể băm

Bạn đã bao giờ nhìn thấy thông báo “TypeError. loại không thể xóa được” khi chạy chương trình Python của bạn?

Thông báo “TypeError. loại không thể băm” xuất hiện trong chương trình Python khi bạn cố gắng sử dụng loại dữ liệu không thể băm ở một vị trí trong mã của bạn yêu cầu dữ liệu có thể băm. Ví dụ: dưới dạng một mục của một bộ hoặc dưới dạng khóa của từ điển

Lỗi này có thể xảy ra trong nhiều tình huống và trong hướng dẫn này, chúng tôi sẽ phân tích một vài trong số chúng để đảm bảo bạn biết phải làm gì khi gặp lỗi này

Hãy sửa nó ngay bây giờ

Mục lục

  • Lỗi Python loại 'Dict' không thể xóa được
  • Loại không thể sửa đổi 'numpy. lỗi Python của ndarray
  • Lỗi loại 'Slice' không thể xóa được trong Python
  • Loại 'Danh sách' không thể xóa được trong Python
  • Lỗi Python 'Đặt' loại không thể xóa được
  • Hàm băm cho các loại dữ liệu khác nhau
  • Phần kết luận

Lỗi Python loại 'Dict' không thể xóa được

Để hiểu khi nào lỗi này xảy ra, hãy sao chép nó trong trình bao Python

Chúng tôi sẽ bắt đầu từ một từ điển chứa một khóa

>>> country = {"name": "UK"}
>>> country
{'name': 'UK'} 

Bây giờ thêm mục thứ hai vào từ điển

>>> country["capital"] = "London"
>>> country
{'name': 'UK', 'capital': 'London'} 

Tất cả đều tốt cho đến nay, nhưng đây là điều sẽ xảy ra nếu do nhầm lẫn, chúng tôi sử dụng một từ điển khác làm khóa

>>> info = {"language": "english"}
>>> country[info] = info["language"]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'dict' 

Loại lỗi không thể xóa được. 'dict' xảy ra vì chúng tôi đang cố gắng sử dụng từ điển làm khóa của mục từ điển. Theo định nghĩa, khóa từ điển cần phải được băm

Nó có nghĩa là gì?

Khi chúng ta thêm một cặp khóa/giá trị mới vào từ điển, trình thông dịch Python sẽ tạo một hàm băm của khóa. Để cung cấp cho bạn ý tưởng về cách một hàm băm trông như thế nào, hãy xem hàm hash[] trả về cái gì

>>> hash["language"]
-79422224077228785
>>> hash[{"language": "english"}]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'dict' 

Bạn có thể thấy rằng chúng tôi đã lấy lại hàm băm cho một chuỗi nhưng khi chúng tôi cố gắng chuyển một từ điển sang hàm băm, chúng tôi nhận lại cùng một lỗi "loại không thể sửa được" mà chúng tôi đã thấy trước đây

Loại không thể băm. Lỗi 'dict' là do các đối tượng có thể thay đổi như từ điển không thể băm được

Loại không thể sửa đổi 'numpy. lỗi Python của ndarray

Hãy cùng xem xét một lỗi tương tự nhưng lần này là lỗi khó hiểu. ndarray [mảng N chiều]

>>> import numpy as np
>>> x = np.array[[[1, 2, 3], [4, 5, 6]]]
>>> type[x]
 

Sau khi xác định một mảng bằng NumPy, hãy tìm hiểu điều gì sẽ xảy ra nếu chúng ta cố gắng chuyển đổi mảng thành một tập hợp

>>> set[x]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'numpy.ndarray' 

Chúng tôi lại thấy lỗi “unhashable type”, tôi muốn xác nhận xem một lần nữa chúng tôi có thấy hành vi tương tự khi chúng tôi cố gắng áp dụng hàm hash[] cho ndarray của mình không

>>> hash[x]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'numpy.ndarray' 

Lỗi y như vậy nhưng tại sao khi chuyển mảng thành tập hợp ta lại gặp lỗi này?

Hãy thử một cái gì đó khác…

Mảng mà chúng ta đã định nghĩa trước đây là hai chiều, bây giờ chúng ta sẽ thực hiện kiểm tra tương tự với mảng một chiều

>>> y = np.array[[1, 2, 3]] 
>>> y
array[[1, 2, 3]]
>>> type[y]

>>> set[y]
{1, 2, 3} 

Nó hoạt động lần này

Lý do tại sao lần chuyển đổi đầu tiên thành một tập hợp không thành công là do chúng tôi đang cố gắng tạo một tập hợp các mảng NumPy nhưng một mảng NumPy có thể thay đổi và do đó nó không thể được sử dụng làm phần tử của một tập hợp

________số 8

Các mục trong một bộ phải được băm. Chỉ các loại bất biến mới có thể băm được trong khi các loại có thể thay đổi như mảng NumPy không thể băm được vì chúng có thể thay đổi và phá vỡ tra cứu dựa trên thuật toán băm

Ví dụ: các chuỗi là bất biến nên một chuỗi các chuỗi sẽ được chuyển đổi thành một tập hợp mà không có bất kỳ lỗi nào

>>> z = np.array[['one', 'two', 'three']]
>>> type[z]

>>> set[z]
{'one', 'two', 'three'} 

Tất cả đều tốt. Hành vi tương tự mà chúng ta đã thấy cũng áp dụng cho danh sách Python bình thường thay vì mảng NumPy

Lỗi loại 'Slice' không thể xóa được trong Python

Loại lỗi không thể xóa được. 'slice' xảy ra nếu bạn cố gắng sử dụng toán tử slice với kiểu dữ liệu không hỗ trợ nó

Ví dụ: bạn có thể sử dụng toán tử lát để lấy một lát của danh sách Python

Nhưng điều gì sẽ xảy ra nếu bạn áp dụng toán tử lát cắt vào từ điển?

Hãy cùng tìm hiểu…

>>> country["capital"] = "London"
>>> country
{'name': 'UK', 'capital': 'London'} 
0

Slice hoạt động trên các chỉ mục và đó là lý do tại sao nó hoạt động trên danh sách và nó không hoạt động trên từ điển

Từ điển được tạo từ các cặp khóa-giá trị và điều này cho phép truy cập bất kỳ giá trị nào bằng cách sử dụng khóa từ điển được liên kết

>>> country["capital"] = "London"
>>> country
{'name': 'UK', 'capital': 'London'} 
1

Loại 'Danh sách' không thể xóa được trong Python

Đây là khi bạn có thể gặp lỗi 'danh sách' loại không thể xóa được trong Python…

Hãy tạo một bộ số

>>> country["capital"] = "London"
>>> country
{'name': 'UK', 'capital': 'London'} 
2

Tất cả đều tốt cho đến nay, nhưng điều gì sẽ xảy ra nếu một trong các phần tử trong tập hợp là một danh sách?

>>> country["capital"] = "London"
>>> country
{'name': 'UK', 'capital': 'London'} 
3

Chúng tôi nhận được lỗi loại không thể sửa được và đó là vì…

Các mục của bộ Python phải không thay đổi nhưng danh sách có thể thay đổi. Điều này là bắt buộc vì các mục của một tập hợp cần có thể băm được và loại dữ liệu có thể thay đổi không thể băm được vì giá trị của nó có thể thay đổi bất cứ lúc nào

Bộ tương tự như một danh sách nhưng không thay đổi được, hãy xem liệu chúng ta có thể tạo một tập hợp cung cấp một bộ thay vì một danh sách như một trong các phần tử của nó không

>>> country["capital"] = "London"
>>> country
{'name': 'UK', 'capital': 'London'} 
4

Lần này không có lỗi

Sự khác biệt giữa danh sách và bộ trong Python là danh sách có thể thay đổi, được đặt trong dấu ngoặc vuông [ ] và không thể băm được. Một bộ dữ liệu là bất biến, được đặt trong dấu ngoặc đơn [] và có thể băm được

Lỗi Python 'Đặt' loại không thể xóa được

Đã đến lúc tìm hiểu xem bạn cũng có thể gặp phải lỗi loại không thể sửa đổi như thế nào khi cố gắng sử dụng một bộ làm mục của một bộ khác

Trước hết, hãy xác định một danh sách các tập hợp

>>> country["capital"] = "London"
>>> country
{'name': 'UK', 'capital': 'London'} 
5

Nó hoạt động tốt vì các phần tử của danh sách có thể thay đổi được

Bây giờ, thay vì định nghĩa một danh sách các tập hợp, chúng ta sẽ cố gắng xác định một tập hợp các tập hợp

Bắt đầu bằng cách tạo một tập hợp trống

>>> country["capital"] = "London"
>>> country
{'name': 'UK', 'capital': 'London'} 
6

Sau đó, chúng tôi sẽ sử dụng phương thức set add để thêm một mục đầu tiên của loại được đặt vào nó

>>> country["capital"] = "London"
>>> country
{'name': 'UK', 'capital': 'London'} 
7

Chúng tôi nhận lại lỗi loại không thể xóa. 'set' bởi vì, như đã giải thích trước đây, các mục của một tập hợp phải không thay đổi và có thể băm [e. g. chuỗi, số nguyên, bộ dữ liệu]

Như một giải pháp thay thế, chúng ta có thể sử dụng một kiểu dữ liệu khác do Python cung cấp. băng giá

Bộ đóng băng là phiên bản bất biến của kiểu dữ liệu bộ Python

Hãy chuyển đổi bộ vật phẩm thành bộ đóng băng

>>> country["capital"] = "London"
>>> country
{'name': 'UK', 'capital': 'London'} 
8

Và bây giờ hãy thêm Frozenset vào set trống mà chúng ta đã xác định trước đó

>>> country["capital"] = "London"
>>> country
{'name': 'UK', 'capital': 'London'} 
9

Nó đã làm việc

Hàm băm cho các loại dữ liệu khác nhau

Chúng tôi đã thấy rằng lỗi loại không thể băm xảy ra khi chúng tôi sử dụng loại dữ liệu không hỗ trợ băm bên trong cấu trúc dữ liệu yêu cầu băm [e. g. bên trong một bộ hoặc dưới dạng khóa từ điển]

Hãy xem xét một số loại dữ liệu Python để xác minh loại nào có thể băm được [chúng cung cấp phương thức __hash__]

Các loại dữ liệu có thể thay đổi không thể băm được. danh sách, bộ, từ điển

>>> info = {"language": "english"}
>>> country[info] = info["language"]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'dict' 
0

Như bạn có thể thấy ở trên, cả ba loại dữ liệu đều không cung cấp phương thức __hash__ [Không trả về]

Các kiểu dữ liệu bất biến có thể băm được. chuỗi, số nguyên, float, tuple, Frozenset

>>> info = {"language": "english"}
>>> country[info] = info["language"]
Traceback [most recent call last]:
  File "", line 1, in 
TypeError: unhashable type: 'dict' 
1

Tất cả các loại dữ liệu này đều có triển khai hàm __hash__, chúng có thể băm được

Phần kết luận

Chúng tôi đã thấy một số trường hợp có thể xảy ra lỗi loại không thể xóa được trong mã Python của bạn

Các loại dữ liệu Python cụ thể yêu cầu dữ liệu có thể băm, ví dụ: các mục của một bộ phải có thể băm được hoặc các khóa của từ điển Python phải có thể băm được

Nếu dữ liệu không thể băm được sử dụng khi dữ liệu có thể băm được yêu cầu thì trình thông dịch Python sẽ đưa ra lỗi loại không thể băm được

Bây giờ bạn đã biết cách tìm ra nguyên nhân gây ra lỗi và cách giải quyết nó bằng cách thay thế kiểu dữ liệu Python không thể băm bằng kiểu dữ liệu có thể băm

Bài viết liên quan

Tìm giá trị tối thiểu và tối đa trong từ điển Python [Từng bước]

Phương thức riêng tư trong Python. Họ có thực sự tồn tại không?

Python có phải là ngôn ngữ kịch bản không?

Claudio Sabato

Tôi là Trưởng nhóm công nghệ, Kỹ sư phần mềm và Huấn luyện viên lập trình. Tôi muốn giúp bạn trong hành trình trở thành Nhà phát triển siêu hạng

Những loại dữ liệu Python nào có thể băm được?

Trong Python, bất kỳ đối tượng bất biến nào [chẳng hạn như số nguyên, boolean, chuỗi, bộ] đều có thể băm, nghĩa là giá trị của nó không thay đổi . Điều này cho phép Python tạo một giá trị băm duy nhất để xác định nó, từ điển có thể sử dụng giá trị này để theo dõi các khóa và bộ duy nhất để theo dõi các giá trị duy nhất.

Giá trị có thể băm trong Python là gì?

Vì vậy, có thể băm là một tính năng của đối tượng Python cho biết đối tượng có giá trị băm hay không . Nếu đối tượng có giá trị băm thì nó có thể được sử dụng làm khóa cho từ điển hoặc làm phần tử trong tập hợp. Một đối tượng có thể băm nếu nó có giá trị băm không thay đổi trong suốt vòng đời của nó.

Hashable nghĩa là gì?

Một loại có thể được băm vào Hasher để tạo ra giá trị băm số nguyên .

Tại sao danh sách là Unhashable và tuple là hashable?

Vì danh sách có thể thay đổi, trong khi bộ thì không . Ví dụ: khi bạn lưu trữ hàm băm của một giá trị trong một lệnh, nếu đối tượng thay đổi, giá trị băm được lưu trữ sẽ không tìm ra, vì vậy nó sẽ giữ nguyên.

Chủ Đề