Python 2 нарушает стандарт Unicode, позволяя вам кодировать кодовые точки в диапазоне от U + D800 до U + DFFF, по крайней мере, в сборке UCS4. От Википедия :
Стандарт Unicode постоянно резервирует эти значения кодовых точек для кодирования UTF-16 суррогатов высокого и низкого уровня, и им никогда не будет назначен символ, поэтому не должно быть оснований для их кодирования. Официальный стандарт Unicode гласит, что никакие формы UTF, включая UTF-16, не могут кодировать эти кодовые точки.
Официальный стандарт UTF-8 не имеет кодировки для кодовых точек суррогатной пары UTF-16, поэтому Python 3 вызывает исключение при попытке:
>>> '\ud83c\udc4f'.encode('utf8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'utf-8' codec can't encode characters in position 0-1: surrogates not allowed
Но поддержка Unicode в Python 2 немного более рудиментарна, и наблюдаемое вами поведение варьируется в зависимости от конкретного варианта сборки UCS2 / UCS4 ; в сборке UCS2 ваши переменные равны :
>>> import sys
>>> sys.maxunicode
65535
>>> a1 = u'\U0001f04f'
>>> a2 = u'\ud83c\udc4f'
>>> a1 == a2
True
, поскольку в такой сборке все кодовые точки, отличные от BMP, кодируются как суррогатные пары UTF-16 (расширение по стандарту UCS2).
Таким образом, в сборке UCS2 нет разницы между вашими двумя значениями, и выбор кодирования в полную кодовую точку, отличную от BMP, полностью допустим , если вы предполагаете, что хотите кодировать U + 1F04F и другие такие кодовые точки. Сборка UCS4 просто соответствует этому поведению.