Python:数据与文本?

Posted

技术标签:

【中文标题】Python:数据与文本?【英文标题】:Python: data vs. text? 【发布时间】:2010-12-16 17:06:11 【问题描述】:

Guido van Rossum 关于Python 3000 的演讲提到了一些最终使从 Python 2 过渡到 Python 3 更容易的事情。他专门讨论了文本处理,因为在 Python 3 中将 Unicode 作为字符串的唯一表示是主要变化之一。

就文本处理而言,一张幻灯片 (#14) 说:

在 2.6 中: 对所有数据使用 bytes 和 b'...'(知道这些只是 str 和 '...' 的别名) 对所有文本使用 unicode 和 u'...' 在 2.5 中: '...' 表示数据,u'...' 表示文本

我使用的是 Python 2.6.4。这对我来说究竟意味着什么?

在 Python 的世界里,数据和文本有什么区别?

【问题讨论】:

【参考方案1】:

简而言之,Py3k 中处理文本和数据的方式可以说是该语言中最“破坏性”的变化。通过了解并尽可能避免某些 Python 2.6 逻辑的工作方式与 3.x 不同的情况,我们可以在发生迁移时促进迁移。然而我们应该预料到 2.6 逻辑的某些部分可能需要特别注意和修改,例如处理不同的编码等。

BDFL 在幻灯片 14 上的建议背后的想法可能是开始“使用” Py3k 支持的相同类型(并且仅支持这些类型),即字符串的 unicode 字符串(str 类型)和 8 -bits 字节序列用于“数据”(bytes 类型)。

上一句中的术语“using”使用得相当松散,因为这些类型的语义和相关的存储/编码在 2.6 和 3.x 版本之间有所不同。在 Python 2.6 中,字节类型和相关的文字语法 (b'xyz') 只是映射到 str 类型。因此

# in Py2.6
>>'mykey' == b'mykey'
True
b'mykey'.__class__
<class 'str'>

# in Py3k
>>>'mykey' == b'mykey'
False
b'mykey'.__class__
<class 'bytes'>  

为了回答您的问题[在下面的评论中],在 2.6 中,无论您使用 b'xyz' 还是 'xyz',Python 都将其理解为相同的一件事:str。 重要的是将这些理解为[可能/在未来]具有不同目的的两种不同类型

str 用于类似文本的信息,以及 字节的八位字节序列存储手头的任何数据。

例如,再次接近您的示例/问题,在 Py3k 中,您将能够拥有一个包含两个元素的字典,这些元素具有相似的键,一个带有 b'mykey',另一个带有'mykey',但是在 2.6 下这是不可能的,因为这两个键实际上是相同的;重要的是你知道这类事情并避免(或在代码中以特殊方式显式标记)2.6 代码在 3.x 中不起作用的情况。

在 Py3k 中,str 是一个抽象的 unicode 字符串,一个 unicode 代码点(字符)序列,Python 处理将其转换为/从其编码形式(无论编码可能是什么)(作为程序员,您确实对编码,但在您处理字符串操作时,您无需担心这些细节)。相反,字节是一个 8 位“事物”序列,其语义和编码完全留给程序员。

因此,即使 Python 2.6 没有发现差异,通过显式使用 bytes() / b'...' 或 str() / u'...',你...

...为即将到来的 Py3k 类型和语义做好准备 ... 使源代码的自动转换(2to3 工具或其他)更容易,从而 b'...' 中的 b 将保留,u'...' 中的 u 将被删除(因为唯一的字符串类型将是 unicode)。

更多信息Python 2.6 What's new(见 PEP 3112 字节文字)Python 3.0 What's New(见顶部附近的Text Vs. Data Instead Of Unicode Vs. 8-bit

【讨论】:

让你真正考虑一下你的意思是一串字符还是一串字节也是一个好习惯!唯一的问题当然是你失去了与 Python 2.5 及更早版本的兼容性。 我明白为什么这样做是个好主意,但我仍然不清楚如何。除非一个函数明确地需要一个字节串,否则我什么时候使用一个字节串和一个字符串? my_dict[b'mykey'] 还是 my_dict[u'mykey']?什么时候算数据,什么时候算文本? @cschol:我建议它始终是一个(unicode)字符串,除非它不是。也就是说,始终使用 unicode 字符串。当您发现这不适用于特定问题时,请使用字节字符串。 @Bryan Oakley ...和猎物。 ;)【参考方案2】:

第一个问题的答案很简单:在 Python 2.6 中,你可以做你习惯的事情。但是,如果您愿意,您可以通过键入以下内容切换到 Py3k 标准:

from __future__ import unicode_literals

您的第二个问题需要进一步澄清:

字符串是打印为人类字符的数据。不仅在 Python 中,而且在处理字符串时,每种语言(我所知道的)都有自己的方式。

但是,共同点是编码。编码是将字节序列映射到字形(即大多数可打印符号)的方式。

Python 提供了一种简单的方法来克服管理编码的复杂性(当您将字符串文字放入代码中时)。

让我们看一个非常简单的例子:

>>> len("Mañana")
7

我只看到 6 个符号。所以我希望len 会返回 6。这个额外的“符号”来自哪里?那么在 UTF-8 中,符号 ñ 用 2 个字节表示。在 Py3k 之前,字符串文字只是字节序列。因此,Python 将该字符串视为字节并将它们全部计数:Ma\xc3\xb1ana

但是,如果我执行以下操作:

>>> len(u"Mañana")
6

所以 Python“知道”“ñ”的 2 字节序列被视为单个字母。

这绝不是 Python 独有的。以下 php 脚本显示了相同的行为:

manu@pavla:~$ php <<EOF
<?php
echo strlen("Mañana")."\n";
?>
EOF
7

PHP 解决方案恰好更复杂:

manu@pavla:~$ php <<EOF
<?php
echo mb_strlen("Mañana", "utf-8")."\n";
?>
EOF
6

请注意,我必须将mb_strlen 替换为strlen,并且我必须将utf-8(编码)作为第二个参数传递。

警告:用户提供的字符串通常以字节的形式出现,而不是 unicode 字符串。所以你需要照顾好它。查看更多关于http://mail.python.org/pipermail/python-list/2008-July/139193.html

【讨论】:

“编码是将字节序列映射到字形(即大多数可打印符号)的方式”。这不太对。它们是字节序列到字符的映射,无论这些字符是否被打印。将字符映射到字形完全是另一个过程,取决于字体系统。 @quark。我同意。我试图简化相当大的响应的话语。

以上是关于Python:数据与文本?的主要内容,如果未能解决你的问题,请参考以下文章

知识共享python网络爬虫与文本数据分析

seo与python大数据结合给文本分词并提取高频词

那些年,我们开始学Python网络爬虫与文本挖掘

python数据挖掘——文本分析

python数据分析与挖掘学习笔记_小说文本数据挖掘part1

python数据分析与挖掘学习笔记_小说文本数据挖掘part2