2013-04-24 46 views
8

Tôi muốn kiểm tra sự hiện diện của một từ khóa trong từ điển là 'nếu khóa không có trong từ điển: làm điều gì đó' Tôi đã thực hiện điều này nhiều lần, nhưng lần này nó hoạt động kỳ lạ.python 2.7 hiện diện trong từ điển

đặc biệt:

termCircuit = termCircuitMap[term] 

lợi nhuận KeyError

khi tôi sửa lỗi mã này trong Eclipse PyDev, tôi đã nhận (biểu thức sử dụng) như sau:

term in termCircutiMap  # prints False 
term in termCircuitMap.keys() # prints True 

Đừng ai hiểu làm thế nào đây là khả thi? Tôi nghĩ rằng nếu một cái gì đó là 'trong' bộ chìa khóa thì nó là 'trong' từ điển.

Tôi đang đính kèm ảnh chụp màn hình đánh giá.

http://img836.imageshack.us/img836/1274/screenshotpython.png

Cảm ơn rất nhiều cho việc giải thích :)

+1

điều này lạ ... có bất kỳ mã nào giữa hai câu lệnh có điều kiện này không? –

+1

Nếu bạn đang thực sự chạy hai dòng đó ngay lập tức, không có lời giải thích nào cho lỗi này. 'key trong aDict' thực sự nhanh hơn và vượt trội hơn' key trong aDict.keys() ', nhưng chúng _should_ cả hai đều trả về cùng một giá trị. Có thể một cái gì đó đã sửa đổi từ điển giữa những kiểm tra? –

+9

Bạn có thể hiển thị ví dụ về mã thực tế thể hiện sự cố không? Loại chìa khóa trong dict của bạn là gì? Hành vi này có thể thực hiện được nếu các khóa là các đối tượng với các định nghĩa băm/bình đẳng không tương thích. – BrenBarn

Trả lời

11

Bạn có thể thấy hành vi này nếu chức năng của chìa khóa của bạn __hash__ là không đúng quy định. Ví dụ: thông tin sau cung cấp cho hành vi tương tự như bạn mô tả:

import random 

class Evil(int): 
    def __hash__(self): 
     return random.randint(0, 10000) 

evil_vals = [Evil(n) for n in range(10)] 

dict_with_evil_keys = dict((evil_val, None) 
          for evil_val in evil_vals) 

print evil_vals[0] in dict_with_evil_keys # prints False 
print evil_vals[0] in dict_with_evil_keys.keys() # prints True 

Trong trường hợp này, tôi tạo ra giá trị băm ngẫu nhiên, rõ ràng là một ý tưởng tồi. Một vấn đề ít rõ ràng hơn sẽ có tác dụng tương tự có thể là nếu giá trị khóa của bạn có thể thay đổi. (Thông thường, các giá trị có thể thay đổi sẽ không bao giờ được xác định __hash__ và không được sử dụng làm khóa trong từ điển.)

+2

Gah! Đã khiến tôi quá lâu để viết cùng một thứ. Điều duy nhất tôi có thể thêm là liên kết đến các quy tắc cho phương thức '__hash__': http://docs.python.org/2/reference/datamodel.html#object.__hash__ –

+0

Cảm ơn bạn, dường như vấn đề là tôi nghĩ rằng các đối tượng là bất biến nhưng chúng không.Vì vậy, đây là cách giải thích tình huống này có thể xảy ra như thế nào, nếu ai đó tò mò: o = SomeClass() #wrongly được cho là bất biến – jlanik

+0

Ok, xin lỗi các bạn, tôi sẽ ngớ ngẩn khi viết mã trong các nhận xét. Vì vậy, đây là ví dụ: o = SomeClass() bản đồ [o] = Không #now băm (o) == x đột biến (o) #now băm (o) == y o trong bản đồ #prints Sai, bởi vì băm của o là x khi nó được thêm o trong map.keys() #prints Đúng, vì map.keys() là một danh sách và sự hiện diện trong danh sách không được kiểm tra bằng cách tính toán băm (i đoán ...) – jlanik