Các mã hóa ASCII chỉ bao gồm các byte với giá trị <= 127
. Phạm vi của các ký tự đại diện bởi các byte này giống hệt nhau trong hầu hết các mã hóa; nói cách khác, "A" là chr(65)
bằng ASCII, bằng latin-1, UTF-8, v.v.
Ký hiệu một nửa, không phải là một phần của bộ ký tự ASCII, vì vậy khi Python cố gắng mã hóa biểu tượng này thành ASCII, nó không thể làm gì ngoài thất bại.
Cập nhật: Dưới đây là những gì xảy ra (tôi giả sử chúng ta đang nói CPython):
float(u'\xbd')
dẫn đến PyFloat_FromString
trong floatobject.c được gọi. Hàm này, cho đối tượng unicode, lần lượt gọi PyUnicode_EncodeDecimal
trong số unicodeobject.c đang được gọi. Từ skimming qua mã, tôi nhận được nó rằng chức năng này biến đối tượng unicode thành một chuỗi bằng cách thay thế mỗi ký tự bằng một mã số unicode <256
với byte của giá trị đó, tức là một nửa ký tự, có codepoint 189, được chuyển thành chr(89)
.
Sau đó, PyFloat_FromString
hoạt động như bình thường. Tại thời điểm này, nó làm việc với một chuỗi thông thường, mà xảy ra có chứa một byte byte không phải ASCII. Nó không quan tâm về điều này; nó chỉ tìm thấy một byte mà không phải là một chữ số, một khoảng thời gian hoặc tương tự, do đó, nó làm tăng lỗi giá trị.
Đối số cho ngoại lệ này là một chuỗi
"invalid literal for float(): " + evil_string
Đó là tốt; một thông báo ngoại lệ, sau khi tất cả, một chuỗi. Chỉ khi bạn cố gắng giải mã chuỗi này, sử dụng ASCII mã hóa mặc định, điều này biến thành một vấn đề.
Điều này có nên được coi là lỗi trong Python không? Lý do của tôi: nếu float() nhận được một chuỗi Unicode, nó sẽ ném một ngoại lệ được mô tả bằng Unicode nếu thông báo sẽ bao gồm đầu vào. Nếu không, các ngoại lệ không thể được xử lý an toàn, như ví dụ cho thấy. – pablobm
Tôi nghĩ rằng gọi nó là một lỗi là công bằng - các messaeg lỗi nên có lẽ chứa 'repr (v)' thay vì 'str (s)', như biết giá trị đầu vào ban đầu là hữu ích hơn so với phiên bản mã hóa thập phân. –