当我应该编码或者我要解码时,我总是感到困惑。
我所理解的是,在阅读以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'!
因此,为了测试你是否在我的禁用词列表中,我做了以下内容:
[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: []
所以现在我被困在一个未经过滤的元组列表中。
我做错了什么?
答案 0 :(得分:3)
问题实际上是一个红鲱鱼。该问题与编码和解码无关;相反,问题是你正在比较两种不同的类型。字节字符串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
得到了在写这篇文章时发生在我身上。把它们放在同一个语句中就说明了它们实际上是不同的。)
在Ned Bachtelder的Pragmatic Unicode演示中,非常好地解释了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'
作为字符串。