Подтвердить что ты не робот

Сравнение Python UTF-8

a = {"a":"çö"}
b = "çö"
a['a']
>>> '\xc3\xa7\xc3\xb6'

b.decode('utf-8') == a['a']
>>> False

Что там происходит?

edit = Извините, это была моя ошибка. Это все еще ложь. Я использую Python 2.6 на Ubuntu 10.04.

4b9b3361

Ответ 1

Возможные решения

Либо напишите вот так:

a = {"a": u"çö"}
b = "çö"
b.decode('utf-8') == a['a']

Или как это (вы также можете пропустить .decode('utf-8') с обеих сторон):

a = {"a": "çö"}
b = "çö"
b.decode('utf-8') == a['a'].decode('utf-8')

Или как это (моя рекомендация):

a = {"a": u"çö"}
b = u"çö"
b == a['a']

Описание

Обновлено на основе комментария Тима. В исходном коде b.decode('utf-8') == u'çö' и a['a'] == 'çö', поэтому вы делаете следующее сравнение:

u'çö' == 'çö'

Один из объектов имеет тип unicode, другой - тип str, поэтому для выполнения сравнения str преобразуется в unicode, а затем два объекта unicode в сравнении. Он отлично работает в случае чисто ASCII-строк, например: u'a' == 'a', так как unicode('a') == u'a'.

Однако он не работает в случае u'çö' == 'çö', так как unicode('çö') возвращает следующую ошибку: UnicodeDecodeError: кодек 'ascii' не может декодировать байт 0xc3 в позиции 0: порядковый номер не в диапазоне (128), и, следовательно, целое сравнение возвращает False и выдает следующее предупреждение: UnicodeWarning: Unicode равное сравнение не удалось преобразовать оба аргумента в Unicode - интерпретируя их как неравные.

Ответ 2

b является string, a является dict

Вы хотите (я верю):

b == a['a']

Ответ 3

UTF-8 - это кодировка, используемая для записи текста в Unicode в файлах. Однако в Python вы работаете с объектами, которые имеют фиксированный способ представления текста в Unicode, и таким образом это не UTF-8.

Вы все еще можете сравнить строки Unicode в Python, но это не связано с UTF-8, за исключением того, что если вы хотите поместить константы в эти строки Unicode, вам нужно будет закодировать текст файла, содержащего ваш исходный код, в UTF-8. Как только выполняется оператор присваивания, строка больше не является UTF-8, но теперь является внутренним представлением Python.

Кстати, если вы делаете сравнения с Unicode, вы, вероятно, захотите использовать модуль unicodedata и нормализовать строки до того, как будут выполнены сравнения.

Ответ 4

Try   b == a ['a']

Ответ 5

Вы сравниваете строку с dict.

>>> a = {"a":"çö"}
>>> b = "çö"
>>> a == b
False
>>> a['a'] == b
True

Если вы сравните строку (b) с элементом a (a ['a']), вы получите желаемый результат.

Ответ 6

Убедитесь, что ваш код находится в UTF-8 (NOT Latin-1) и/или использует линию кодирования так:

#! /usr/bin/python
# -*- coding: utf-8 -*-
a = {"a": u"çö"}
b = "çö"
assert b == a['a']
assert b.decode('utf-8') == a['a'].decode('utf-8')

Если вы используете юникод по всем направлениям, вы можете импортировать unicode_literals из будущего и сокращать страдания от кодирования:

#! /usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
a = {"a": u"çö"}
b = "çö"
assert b == a['a']
assert b == a['a']
assert b.encode('utf-8') != a['a']
assert b.encode('utf-8') == a['a'].encode('utf-8')

Если файл использует unicode_literals, все "строки" теперь являются объектами "unicode" (для кодирования файла), если они не являются "добавленными" с ab (для эмулирования разделения строк/байтов в Python 3.X).

Ответ 7

NullUserException прав, что это должно быть правильно:

b == a['a']

Вы все еще получаете "False", потому что вы декодируете одну сторону как utf-8 (создавая строку Unicode), в то время как другая сторона остается закодированной байтовой строкой utf-8.