2015-03-17 17 views
5

Trong Python 2.7:Python trả về chiều dài của 2 đối với đơn ký tự Unicode chuỗi

In [2]: utf8_str = '\xf0\x9f\x91\x8d' 
In [3]: print(utf8_str) 

In [4]: unicode_str = utf8_str.decode('utf-8') 
In [5]: print(unicode_str) 
    
In [6]: unicode_str 
Out[6]: u'\U0001f44d' 
In [7]: len(unicode_str) 
Out[7]: 2 

Kể từ unicode_str chỉ chứa một điểm mã unicode duy nhất (0x0001f44d), tại sao len(unicode_str) trở lại 2 thay vì 1?

Trả lời

14

nhị phân Python của bạn được biên dịch với hỗ trợ UCS-2 (hẹp xây dựng) và bên trong bất kỳ thứ gì bên ngoài BMP (Máy bay đa ngôn ngữ cơ bản) được thể hiện bằng cách sử dụng surrogate pair.

Điều đó có nghĩa là các điểm mã như vậy hiển thị dưới dạng 2 ký tự khi yêu cầu độ dài.

Bạn sẽ phải biên dịch lại nhị phân Python để sử dụng UCS-4 thay vào đó nếu điều này quan trọng (./configure --enable-unicode=ucs4 sẽ bật) hoặc nâng cấp lên Python 3.3 hoặc mới hơn, trong đó Python's Unicode support was overhauled để sử dụng loại Unicode có chiều rộng thay đổi ASCII, UCS-2 và UCS-4 theo yêu cầu của các điểm mã chứa.

Trên phiên bản Python 2.7 và 3.0 - 3.2, bạn có thể phát hiện loại công trình bạn có bằng cách kiểm tra sys.maxunicode value; nó sẽ là 2^16-1 == 65535 == 0xFFFF cho bản dựng UCS-2 hẹp, 1114111 == 0x10FFFF cho bản dựng UCS-4 rộng. Trong Python 3.3 và lên nó luôn luôn thiết lập để 1114111.

Demo:

# Narrow build 
$ bin/python -c 'import sys; print sys.maxunicode, len(u"\U0001f44d"), list(u"\U0001f44d")' 
65535 2 [u'\ud83d', u'\udc4d'] 
# Wide build 
$ python -c 'import sys; print sys.maxunicode, len(u"\U0001f44d"), list(u"\U0001f44d")' 
1114111 1 [u'\U0001f44d'] 
+0

bạn có thể sử dụng 'sys.maxunicode' trên Python 3 quá. Nó được ngụ ý nhưng nó là giá trị chỉ ra một cách rõ ràng rằng 'len (u' \ U0001f44d ') == 1' trên Python 3.3+ (hoặc một Python 2 xây dựng rộng) – jfs

+0

@JFSebastian: chắc chắn, nhưng đến 3,3 nó là một hằng số ở đó, như Python 3.3 và chuyển đổi một cách minh bạch giữa ASCII, UCS-2 một bộ lưu trữ UCS-4 cho các chuỗi theo yêu cầu. Và bạn thực sự không muốn sử dụng Python <3.3. –

+0

Không có phân biệt hẹp/rộng trên Python 3.3+ (biểu diễn bên trong không được hiển thị - bạn không quan tâm những gì python sử dụng trong nội bộ). Điểm mà bạn có thể sử dụng 'sys.maxunicode' bất kể phiên bản. – jfs

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