NaN được xử lý hoàn hảo khi tôi kiểm tra sự hiện diện của nó trong danh sách hoặc bộ. Nhưng tôi không hiểu làm thế nào. [UPDATE: không có nó không; nó được báo cáo là hiện tại nếu tìm thấy thể hiện NaN giống hệt nhau; nếu chỉ có trường hợp không giống hệt nhau của NaN được tìm thấy, nó được báo cáo như vắng mặt.]Kiểm tra sự hiện diện NaN trong thùng chứa
Tôi nghĩ sự hiện diện trong danh sách được kiểm tra bằng cách bình đẳng, vì vậy tôi mong đợi NaN để không bị phát hiện kể từ NaN! = NaN.
băm (NaN) và băm (0) là cả 0. Làm cách nào để từ điển và tập hợp cho NaN và 0 cách nhau?
Có an toàn để kiểm tra sự hiện diện của NaN trong một thùng chứa tùy ý bằng cách sử dụng toán tử
in
không? Hoặc là nó thực hiện phụ thuộc?
Câu hỏi của tôi là về Python 3.2.1; nhưng nếu có bất kỳ thay đổi nào hiện có/lên kế hoạch trong các phiên bản sau, tôi cũng muốn biết điều đó.
NaN = float('nan')
print(NaN != NaN) # True
print(NaN == NaN) # False
list_ = (1, 2, NaN)
print(NaN in list_) # True; works fine but how?
set_ = {1, 2, NaN}
print(NaN in set_) # True; hash(NaN) is some fixed integer, so no surprise here
print(hash(0)) # 0
print(hash(NaN)) # 0
set_ = {1, 2, 0}
print(NaN in set_) # False; works fine, but how?
Lưu ý rằng nếu tôi thêm một thể hiện của một lớp người dùng định nghĩa để một list
, và sau đó kiểm tra để ngăn chặn, phương pháp của dụ __eq__
được gọi là (nếu định nghĩa) - ít nhất là trong CPython. Đó là lý do tại sao tôi giả định rằng ngăn chứa list
được kiểm tra bằng cách sử dụng toán tử ==
.
EDIT:
câu trả lời mỗi La Mã, nó có vẻ như __contains__
cho list
, tuple
, set
, dict
cư xử theo một cách rất lạ:
def __contains__(self, x):
for element in self:
if x is element:
return True
if x == element:
return True
return False
tôi nói 'lạ' vì tôi didn' t thấy nó giải thích trong tài liệu (có lẽ tôi đã bỏ lỡ nó), và tôi nghĩ rằng đây là một cái gì đó mà không nên để lại như là một sự lựa chọn thực hiện.
Tất nhiên, một đối tượng NaN có thể không giống nhau (theo nghĩa là id
) đối với một đối tượng NaN khác. (Điều này không thực sự đáng ngạc nhiên; Python không bảo đảm danh tính đó. Thực ra, tôi chưa bao giờ thấy CPython chia sẻ một cá thể NaN được tạo ra ở những nơi khác nhau, mặc dù nó chia sẻ một thể hiện của một số nhỏ hoặc một chuỗi ngắn.) thử nghiệm cho sự hiện diện NaN trong một thùng chứa tích hợp là không xác định.
Điều này rất nguy hiểm và rất tinh tế. Ai đó có thể chạy đúng mã tôi đã trình bày ở trên và kết luận không chính xác rằng việc kiểm tra thành viên NaN là an toàn khi sử dụng in
.
Tôi không nghĩ rằng có giải pháp hoàn hảo cho vấn đề này. Một cách tiếp cận rất an toàn là đảm bảo rằng NaN không bao giờ được thêm vào các thùng chứa tích hợp. (Đó là một nỗi đau để kiểm tra rằng trong tất cả các mã ...)
lựa chọn khác là xem ra đối với trường hợp có thể có in
NaN ở phía bên trái, và trong những trường hợp như vậy, thử nghiệm cho thành viên NaN riêng, sử dụng math.isnan()
. Ngoài ra, các hoạt động khác (ví dụ: giao lộ được đặt) cũng cần phải tránh hoặc viết lại.
Bottonline: để sử dụng an toàn: bất kỳ (math.isnan (phần tử) cho phần tử trong list_) – jsbueno
@jsbueno: Yup ... Nhưng điều đó không giúp được gì với vấn đề giao cắt được đặt; cũng không xử lý trường hợp của 'cho x trong cont1: nếu x trong cont2 làm một cái gì đó' ... Tôi muốn nói dòng dưới cùng là" rất sợ, và chỉ hy vọng bạn không bỏ qua một cái gì đó " – max
Nó thắng ' t giúp - và bạn phải đồng ý không có giải pháp dễ dàng. Bạn có thể sử dụng vòng lặp ở trên để chuyển đổi bất kỳ NaN nào thành chuỗi đọc "NaN" - những thứ này sẽ so sánh một cách vô cùng. – jsbueno