2014-10-09 14 views
8

khi tạo một bộ:Tại sao bộ python giữ False và Zero độc quyền?

>>> falsey_set = {0, '', False, None} # set([False, '', None]) 
>>> falsey_set = {False, '', 0, None} # set([0,'', None]) 
>>> # adding an item to the set doesn't change anything either 
>>> falsey_set.add(False) # set([0,'',None]) 

hoặc một cuốn từ điển, mà bắt chước hành vi hơi:

>>> falsey_dict = {0:"zero", False:"false"} # {0:'false'} # that's not a typo 
>>> falsey_dict = {False:'false', 0:'zero'} # {False: 'zero'} # again, not a typo 
>>> falsey_set.add(()) # set([0,'', None,()]) 
>>> falsey_set.add({}) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unhashable type: 'dict' 
>>> falsey_dict[()] = 'list' # {False:'zero',():'list'} 
>>> falsey_dict({}) = 'dict' 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unhashable type: 'dict' 

0False luôn loại bỏ một số khác từ các thiết lập. Trong trường hợp từ điển chúng không chính xác hoàn toàn. Có lý do nào cho số này không? Trong khi tôi nhận ra rằng boolean có nguồn gốc từ số nguyên trong Python. Lý do pythonic cho hành động theo cách này trong bối cảnh của bộ đặc biệt là gì (Tôi không quan tâm đến từ điển quá nhiều)? Kể từ khi hữu ích trong việc so sánh truthy như:

>>> False == 0 # True 

Có giá trị rõ ràng trong sự khác biệt:

>>> False is 0 # False 

Tôi đã nhìn qua documentation và dường như không thể tìm thấy một tài liệu tham khảo cho các hành vi

cập nhật

@de lnan Tôi nghĩ rằng bạn đánh vào đầu móng với định nghĩa băm mà bạn đã đề cập trong phần bình luận. Như @mgilson lưu ý cảFalse0 sử dụng chức năng tương tự băm, tuy nhiên để làm object và nhiều người trong lớp con của nó (nghĩa là .: super) có giống hệt băm chức năng. Khóa có vẻ nằm trong cụm từ Hashable objects which compare equal must have the same hash value từ số documentation. Vì, False == 0 và cả hai đều có thể bẻ khóa, kết quả đầu ra của chúng phải theo định nghĩa của Python là tương đương. Cuối cùng, định nghĩa của hashable cho biết bộ sử dụng tính băm trong thành viên đã đặt như sau: Hashability makes an object usable as a dictionary key and a set member, because these data structures use the hash value internally. Mặc dù tôi vẫn không hiểu tại sao cả hai đều sử dụng cùng chức năng băm - tôi có thể giải quyết vấn đề này.

Nếu tất cả chúng tôi đồng ý thì ai đó đề xuất câu trả lời được đánh bóng và tôi sẽ chấp nhận câu trả lời đó. Nếu có thể có một số cải tiến hoặc nếu tôi rời khỏi cơ sở thì hãy để nó được biết dưới đây.

+0

Tại sao danh tính lại quan trọng? Hai chuỗi bằng nhau có thể có các định danh khác nhau, hãy tưởng tượng nỗi đau nếu chúng được xem là khác biệt bởi các bộ và chữ cái. Cũng lưu ý rằng theo định nghĩa của hashability, 'hash (x) == hash (y)' ** phải ** giữ khi 'x == y'. – delnan

+0

Câu hỏi liên quan: http://stackoverflow.com/questions/2764017/is-false-0-and-true-1-in-python-an-implementation-detail-or-is-it-guarante. –

+1

Bạn không nên quá treo lên phần băm của điều này; nó hầu như không liên quan.Câu trả lời đơn giản là dict và set (và list, come to that) thành viên dựa trên * equality * (trừ khi bạn muốn nitpick, trong trường hợp đó mô tả tốt hơn là identity-then-equality), và vì 'False == 0', chúng được coi là giống nhau khi được sử dụng làm yếu tố thiết lập hoặc các phím từ điển. Thực tế là các dicts và các bộ sử dụng một bảng băm (và do đó các phím và các phần tử phải được hashable, và bình đẳng nên ngụ ý bình đẳng của băm) là thứ yếu. –

Trả lời

3

Đó là vì False0băm với giá trị tương tự đều bình đẳng.

Lý do mà họ băm để cùng giá trị là vì bool là một lớp con của int nên bool.__hash__ chỉ đơn giản gọi là cơ tiềm ẩn tương tự mà int.__hash__ cuộc gọi ...

>>> bool.__hash__ is int.__hash__ 
True 
+1

Nếu chúng bằng nhau và [băm] (https://docs.python.org/3/glossary.html#term-hashable), chúng * phải * băm thành cùng một giá trị. @RogerFan – delnan

+0

@delnan - Không chính xác. Nó khá dễ dàng để nấu ăn một ví dụ contrived nơi hai đối tượng băm với cùng một giá trị nhưng không bằng nhau ... – mgilson

+0

Tôi nghĩ rằng tranh cãi bởi mối quan hệ lớp con là đặt giỏ hàng trước khi con ngựa. 'True' và' False' được dự định là các số nguyên 1 và 0 với 'repr()' khác nhau, đó là lý do tại sao chúng được thực hiện dưới dạng lớp con của 'int'. – delnan

0

Đầu tiên, chúng ta hãy cố gắng giải thích những gì đang xảy ngay từ đầu, với số falsey_setfalsey_dict, vì vậy bạn thấy rằng nó không phải là "không chính xác", nhưng trên thực tế, chỉ có thể có giải pháp nhất quán. Để làm như vậy, chúng tôi sẽ xóa bool giây khỏi hình ảnh tạm thời và sử dụng thứ gì đó mà nhiều người nắm bắt trực quan hơn: số thập phân.

>>> numset = {3, 5, 3.0, 4} # {3.0, 4, 5} 
>>> numset.add(3)   # no change 

Tôi hy vọng bạn đồng ý rằng đây chính xác là cách set sẽ hoạt động.Nếu không, thì có vẻ như bạn nghĩ rằng 33.0 không thực sự bằng nhau, hoặc bạn nghĩ rằng một tập hợp nên được phép có các phần tử bằng nhau. Cả hai đều không thực sự tin tưởng IMO.

(Tất nhiên, trong đó trong số 3 và 3.0 kết thúc trong bộ là vấn đề hiển thị chế biến và đặt hơi kỳ lạ vì nó là một dict atrophied nơi khóa và giá trị giống nhau. là phù hợp và quy định tại Pythton. Hiện tại, điểm này chắc chắn là chúng không thể cả hai đều có trong một bộ.)

Một điểm nữa: như bạn thấy, điều tôi có thể thêm nhiều thứ khác vào bộ của tôi (như 45) không quan trọng chút nào. Tương tự, thực tế bạn có thể thêm nhiều thứ sai khác trong tập hợp của bạn (như ''None) không quan trọng chút nào. Sự thật là một cá trích đỏ. Một tập hợp có thể có các phần tử đúng và các phần tử sai. Những gì không thể có, là bằng yếu tố.

>>> numdict = {3:"a", 3.0:"b"} # {3:"b"} 

Điều này trông có vẻ kỳ lạ hơn, nhưng thực tế là điều rõ ràng hơn, vì khóa và giá trị riêng biệt. quy tắc Python là chính xác: đọc màn dict từ trái sang phải, tận dụng mọi cặp một: b, sau đó nếu chính một đã nằm trong dict, cập nhật giá trị của nó để b, nếu không chèn key một vào dict với giá trị b.

Với thuật toán đó, tôi đoán nó rõ ràng như thế nào cuối cùng dict kết thúc lên như vậy, và tất cả các hành vi khác mà bạn đã nhận thấy. Điều quan trọng là, giống như trong một bộ, những gì bạn thực sự cần trong một dict là chỉ có một giá trị cho bất kỳ khóa nhất định nào. Có hai khóa bằng nhau trong cùng một dict sẽ là một lời mời đến thảm họa, kể từ đó bạn sẽ có thể gán cho họ các giá trị khác nhau.

Tóm lại: Tôi nghĩ bạn tự đào sâu với hàm băm và các công cụ triển khai khác. Đây là cách hay để xem cách Python thực hiện X, sau khi bạn nhận ra rằng X là điều đúng đắn cần làm. Nhưng trước tiên bạn phải thấy rằng X là điều đúng đắn để làm. Và tôi hy vọng tôi đã thể hiện điều đó với bạn bây giờ. Một tập hợp không thể có các phần tử bằng nhau. Nó sẽ đánh bại một mục đích được sử dụng rộng rãi của một bộ, loại bỏ các bản sao. Và 3 và 3.0 thực sự là như nhau. Điều này không liên quan gì đến các loại, một số phần mềm nhúng rất tự nhiên, chúng tôi đã xóa chúng ở cấp độ toán học.

Tất nhiên, điều đó để lại câu hỏi "tại sao 0 và False thực sự bình đẳng"? Trong thực tế, câu trả lời không phải là rất khác nhau: chỉ là một nhúng toán học bị xóa đó là vô cùng hữu ích, chúng tôi sẽ phải nhảy qua nhiều hoops vô lý mà không có nó. Để biết thêm về điều đó, hãy đọc về khung Iverson. ;-) Nhưng dù sao, có vẻ như bạn biết về phần đó. Trên đây là những gì đã được vấn đề, tôi đoán.

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