python何时编码以及何时解码?

时间:2015-12-04 11:22:00

标签: python python-2.7 encoding

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

我所理解的是,在阅读以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: []

所以现在我被困在一个未经过滤的元组列表中。

我做错了什么?

1 个答案:

答案 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'作为字符串。