python何时编码,何时解码?

python何时编码,何时解码?,python,python-2.7,encoding,Python,Python 2.7,Encoding,当我应该编码或解码时,我总是感到困惑 我所理解的是,当阅读utf8编码的文本时,我必须解码。(因此,当读取->解码时) 当我写的时候,我需要用utf8编码。(因此,当写入->编码时) 但我偶然发现了一个奇怪的场景 我有一个停止词列表: st = ['la', 'le', ...] 我需要过滤掉包含这些停止词的元组列表 为了测试过滤器方法,我执行了以下操作: t = [(1, 'a'), (1, 'b'), (1, 'c')] # list of tuples st = ['b'] # l

当我应该编码或解码时,我总是感到困惑

我所理解的是,当阅读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'in,我做了以下操作:

[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: []
所以现在我被一个未过滤元组的列表困住了


我做错了什么

这个问题其实是在转移视线。问题与编码和解码无关;相反,问题是您正在比较两种不同的类型。字节字符串
绝不等同于具有相同内容的Unicode字符串

您可以改为使用
=
,但请参见下文:

>>> u'la' == 'la'
True
即使类型强制也无助于传递
is
等价性:

>>> u'la' is unicode('la')
False
。。。因为
比较身份,而不是内容

>>> '{0} {1}'.format(id(u'la'), id(unicode('la')))
'4458408432 4458408480'
4458408432不是4458408480,因此
不是true

(如果您使用了
id(u'la')
后跟
id(unicode('la'))
您可能会误导性地获得相同的
id
两次,因为第一个id被快速垃圾收集,然后它的
id
被重新使用。这发生在我写这篇文章的时候。将它们放在同一条语句中说明它们实际上是多么不同。)

Unicode字符串和字节字符串之间的差异以及编码和解码功能在Ned Bachtelder的演示中得到了很好的解释。最基本的建议是,在阅读任何内容后立即对其进行解码,并仅在需要输出时对其进行编码,这是非常有用的建议。在代码中使用Unicode字符串(当然,当您确实需要将字节设置为字节而不是字符时除外),这样您就不会有不愉快的惊喜

# Note the u' prefix throughout!
st = [u'au', u'aux', u'avec', u'ce', u'ces', u'le', u'la']

当然,在Python3中,
u'
前缀是多余的,因为Unicode字符串是默认值。但是对于Python2,或者需要在两种平台上工作的代码(或者只需要清楚字符串类型),请始终使用
u'
来比较字符串。

我还没有完全理解这些,但您绝对不应该使用
is
来比较字符串<代码>如果st='la'
应该可以正常工作。@DanielRoseman你说得对极了!谢谢你,伙计!您使用的是哪一版本的python?您可能会发现这篇文章很有用:,它是由经验丰富的Ned Batchelder编写的。@quamrana我正在使用python 2.7.10