2012-11-28 27 views
5

Tại sao tôi có thể thêm các cuộc gọi và phương thức thông thường vào một tập hợp chứ không phải là <some list>.append (ví dụ)?Tại sao tôi không thể thêm <some list> .gửi một bộ python?

Ví dụ:

>>> l = [] 
>>> s = set() 
>>> s.add(l.append) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unhashable type: 'list' 
>>> type(l.append) 
<type 'builtin_function_or_method'> 
>>> type(map) 
<type 'builtin_function_or_method'> 
>>> s.add(map) 
>>> def func(): print 'func' 
... 
>>> s.add(func) 
>>> print s 
set([<built-in function map>, <function func at 0x10a659758>]) 

Edit: Tôi nhận thấy rằng l.append.__hash__() cũng cho lỗi này

+0

gì được bạn * thực sự * cố gắng để làm gì? o_O –

+0

@KarlKnechtel Tôi đang viết các bài kiểm tra bằng cách sử dụng twisted.trial. Tôi có một hệ thống xe buýt sự kiện đăng ký callback cho một sự kiện (được chỉ định bởi một chuỗi) và lưu trữ các cuộc gọi lại trong một tập hợp để ngăn chặn các bản sao. Gọi lại cụ thể này chỉ là một trình bao bọc xung quanh results_list.append vì vậy tôi đã cố gắng đăng ký trực tiếp đó như một cuộc gọi lại. Thử nghiệm kích hoạt một sự kiện và kiểm tra results_list để xem nó có chứa dữ liệu hay không. –

Trả lời

7

Bạn không thể thêm list giây vào danh sách vì danh sách có thể thay đổi. Chỉ có thể thêm các đối tượng bất biến vào bộ.

l.append là phương pháp thể hiện. Bạn có thể nghĩ về nó như thể nó là một tuple (l, list.append) — có nghĩa là, đó là phương thức list.append() gắn với danh sách cụ thể l. Phương thức list.append() là không thay đổi nhưng l thì không. Vì vậy, trong khi bạn có thể thêm list.append vào nhóm bạn không thể thêm l.append.

này hoạt động:

>>> s.add(list.append) 

này không hoạt động:

>>> s.add((l, list.append)) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unhashable type: 'list' 
+0

Tôi đã sửa chữa. Không ngạc nhiên khi tôi giả sử, ... Điều đáng ngạc nhiên là tôi đã trải qua cuộc sống luôn nghĩ rằng tất cả các bộ dữ liệu đều có thể băm được :) – mgilson

+1

Hành vi này có ý nghĩa. Ban đầu tôi nghĩ rằng bạn có thể quay trở lại đối tượng ID, nhưng điều đó không hiệu quả vì bạn làm gì khi bạn cố gắng lập chỉ mục từ điển của bạn với một bộ tƣơng tự khác (tƣơng đương): 'd [(500,600)] = ...'. Vì ID là khác nhau, trường hợp sử dụng phổ biến đó sẽ không thành công.Cách duy nhất để băm tuple một cách đáng tin cậy là băm từng phần tử. Rất thú vị. – mgilson

3

Bạn sẽ không cố gắng để thêm list.append. Bạn đang cố gắng thêm l.append là phương thức thể hiện chứ không phải phương thức lớp. Các trường hợp list không thể băm, và rõ ràng các phương thức của chúng không thể bẻ khóa được.

Hãy suy nghĩ theo cách này. Bạn có 2 danh sách:

lfoo = [] 
lbar = [] 

Bây giờ bạn muốn thêm gắn thêm tương ứng để thiết lập của bạn:

s = set() 
s.add(lfoo.append) 
s.add(lbar.append) 

Bây giờ khi bạn thực hiện tra cứu băm cho các thiết lập, bạn không thể chỉ dựa vào phần chức năng của phương thức thể hiện. Thật vậy, lfoolbar cuối cùng sử dụng cùng chức năng (list.append). Vì vậy, đó không phải là một băm duy nhất. Cách bạn làm cho nó độc đáo là bằng cách gắn nó vào một thể hiện. Tuy nhiên, cá thể không hỗ trợ băm, do đó, tập hợp không có cách nào để nói sự khác biệt giữa lfoo.appendlbar.append.

+0

Cảm ơn, đã cập nhật câu hỏi để tham khảo .append, not list.append –

2

Trong Python, list đối tượng không thể băm. Tôi nghi ngờ rằng khi bạn băm một phương thức thể hiện, nó kết hợp băm của cá thể của nó. Như vậy, bạn nhận được TypeError.

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