当我应该编码或当我解码时,我总是很困惑。
我所理解的是,当读取以 utf8 编码的文本时,我必须解码。 (所以当读取->解码时)
当我编写时,我需要将其编码为 utf8。 (所以当写入->编码时)
但是我偶然发现了一个奇怪的场景。
我有一个停用词列表:
st = ['la', 'le', ...]
我需要过滤掉包含任何这些停用词的元组列表。
为了测试过滤方法,我执行了以下操作:
t = [(1, 'a'), (1, 'b'), (1, 'c')] # list of tuples
st = ['b'] # list of stopwords
# print all tuples which are not in st
print [tup for tup in t if any(i not in tup for i in st)]
output: [(1, 'a'), (1, 'c')]
这样就可以了。
现在,当我将其付诸实现时,我没有得到相同的结果。
停用词列表:
# -*- coding: utf-8 -*-
stop_words = {
'fr':
[
'au', 'aux', 'avec', 'ce', 'ces',
'le', 'la'
]
要过滤的元组:
[(0.11363636363636366, u'arch'), (0.09090909090909093, u's'), (0.06818181818181819, u'la'), (0.04545454545454546, u'av'), (0.04545454545454546, u'champs'), (0.04545454545454546, u'de'), (0.04545454545454546, u'des'), (0.04545454545454546, u'grande'), (0.04545454545454546, u'ground'), (0.04545454545454546, u'm')]
过滤元组
[(0.11363636363636366, u'arch'), (0.09090909090909093, u's'), (0.06818181818181819, u'la'), (0.04545454545454546, u'av'), (0.04545454545454546, u'champs'), (0.04545454545454546, u'de'), (0.04545454545454546, u'des'), (0.04545454545454546, u'grande'), (0.04545454545454546, u'ground'), (0.04545454545454546, u'm')]
我还有:u'la'!
因此,为了测试 u'la' 是否在我的停用词列表中,我执行了以下操作:
[st for st in rs.stop_words['fr'] if st is 'la']
output: ['la']
但如果我这样做:
[st for st in rs.stop_words['fr'] if st is u'la']
output: []
该死!
我尝试了以下方法,但没有成功:
[st for st in rs.stop_words['fr'] if st is u'la'.encode('utf8')]
output: []
[st for st in rs.stop_words['fr'] if st is u'la'.decode('utf8')]
output: []
所以现在我陷入了未过滤元组的列表。
我做错了什么?
最佳答案
这个问题确实是一个转移注意力的问题。该问题与编码和解码无关;相反,问题是您正在比较两种不同的类型。一个字节字符串is
永远不会等同于具有相同内容的 Unicode 字符串。
你可以做的(但见下文)是使用 ==
相反:
>>> u'la' == 'la'
True
即使类型强制也无助于通过 is
等价:
>>> u'la' is unicode('la')
False
...因为is
比较的是身份,而不是内容。
>>> '{0} {1}'.format(id(u'la'), id(unicode('la')))
'4458408432 4458408480'
4458408432 不是 4458408480,所以 is
事实并非如此。
(如果你这样做了 id(u'la')
,然后是 id(unicode('la'))
,你可能会误导性地获得相同的 id
两次,因为第一个被快速垃圾收集,然后它的 id
被重用。我在写这篇文章时发生过这种情况.将它们放在同一个语句中表明它们实际上是不同的。)
Unicode 字符串和字节字符串之间的差异以及编码和解码函数在 Ned Bachtelder 的 Pragmatic Unicode 中得到了很好的解释。推介会。基本建议是在阅读任何内容后立即对其进行解码,并仅在需要输出时对其进行编码,这是非常有用的建议。在整个代码中使用 Unicode 字符串(当然,除非您确实需要字节是字节,而不是字符),并且您不会遇到不愉快的意外。
# Note the u' prefix throughout!
st = [u'au', u'aux', u'avec', u'ce', u'ces', u'le', u'la']
当然,在Python 3中,u'
前缀是多余的,因为 Unicode 字符串是默认的。但对于 Python 2 或需要在两个平台上工作的代码(或只需要清楚字符串类型),请始终使用 u'
对于字符串。
关于python 何时编码、何时解码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34087227/