4

给定两个几乎相同的文本文件(纯文本,在 MacVim 中创建),将它们读入 Python 中的变量时会得到不同的结果。我想知道为什么会这样以及如何产生一致的行为。

例如,f1.txt 如下所示:

This isn't a great example, but it works.

f2.txt 看起来像这样:

This isn't a great example, but it wasn't meant to be. 
"But doesn't it demonstrate the problem?," she said.

当我读入这些文件时,使用如下内容:

f = open("f1.txt","r")
x = f.read()

当我查看控制台中的变量时,我得到以下信息。f1.txt:

>>> x
"This isn't a great example, but it works.\n\n"

和 f2.txt:

>>> y
'This isn\'t a great example, but it wasn\'t meant to be. \n"But doesn\'t it demonstrate the problem?," she said.\n\n'

换句话说, f1 只带有转义的换行符,而 f2 的单引号也被转义了。

repr() 显示发生了什么。首先是 f1:

>>> repr(x)
'"This isn\'t a great example, but it works.\\n\\n"'

f2:

>>> repr(y)
'\'This isn\\\'t a great example, but it wasn\\\'t meant to be. \\n"But doesn\\\'t it demonstrate the problem?," she said.\\n\\n\''

这种行为快把我逼疯了。发生了什么事,我如何使它保持一致?如果这很重要,我会尝试以纯文本形式阅读,对其进行操作,并最终将其写出,以便显示正确转义的字符(用于粘贴到 Javascript 代码中)。

4

2 回答 2

15

Python 为您提供了一个字符串文字,如果您将其返回给 Python,则会产生相同的字符串。这被称为repr()字符串的(“表示”的缩写)。这可能不(实际上可能不会)匹配最初指定的字符串,因为有很多方法可以做到这一点,并且 Python 没有记录任何关于它最初是如何指定的。

它在您的第一个示例周围使用双引号,因为它不包含任何单引号,所以效果很好。第二个字符串包含双引号,因此不能使用双引号作为分隔符。相反,它使用单引号并使用反斜杠来转义字符串中的单引号(它不必以这种方式转义双引号,而且它们的数量比单引号还多)。这使表示尽可能短。

这种行为没有理由让你发疯,也没有必要试图让它保持一致。repr()当您在 Python 的交互模式下查看值时,您只会得到字符串的 。当您实际print或以其他方式使用字符串时,您会得到字符串本身,而不是重构的字符串文字。

如果要获取 JavaScript 字符串文字,最简单的方法是使用json模块:

import json
print json.dumps('I said, "Hello, world!"')
于 2013-09-20T19:12:19.267 回答
7

两者都f1包含f2完全正常的未转义单引号。

repr他们看起来不同的事实是没有意义的。

有多种不同的方式来表示相同的字符串。例如,这些都是等价的文字:

"abc'def'ghi"
'abc\'def\'ghi'
'''abc'def'ghi'''
r"abc'def'ghi"

字符串上的repr函数总是只生成一些作为该字符串有效表示的文字,但您不应该完全依赖于它生成的文字。(事实上​​,你应该很少将它用于除调试以外的任何事情。)


由于该语言没有在任何地方定义它使用什么算法来生成 a repr,因此每个实现的每个版本都可能不同。

他们中的大多数人会尽量聪明,使用单引号或双引号来避免尽可能多的转义内部引号,但即使这样也不能保证。如果您真的想知道特定实现和版本的算法,您几乎必须查看源代码。例如,在 CPython 3.3 中, inside unicode_repr,它计算每种类型的引号数;那么如果有单引号但没有双引号,则"使用'.


如果你想要一个字符串的“the”表示,那么你就不走运了,因为没有这样的东西。但是,如果您想要某个字符串的特定表示形式,那没问题。你只需要知道你想要什么格式;大多数格式,已经有人编写了代码,而且通常在标准库中。您可以制作 C 文字字符串、JSON 编码字符串、适合 ASCII RFC822 标头的字符串……但是所有这些格式彼此(以及 Python 文字)都有不同的规则,因此您必须使用正确的函数来完成这项工作.

于 2013-09-20T19:12:09.850 回答