Python显示`\n`而不是换行

21

我编写了一个函数来创建 SQL 查询的 VALUES 部分:

def query_values(data_iterator):
    return ',\n'.join('\n({})\n'.format(',\n'.join('"{}"'.format(value) for value in data_row)
                                     ) for data_row in data_iterator
                      ),

当我调用这个函数并打印结果时,得到的是:

query_values:
('\n("801",\n"printer",\n"barcode printer")\n,\n\n("844",\n"laptop",\n"windows")\n,\n\n("997",\n"printer",\n"barcode printer")\n',)

内容在一行中显示,而不是换行,因为\n会被显示出来。

最初我只有一个\n,但后来我插入了多个,只是想看看它们是否会被显示出来。

第二个问题是整体周围有括号,而我不想要。

我思考了这两个问题,然后找到了第二个问题的解决方案:

我的函数末尾有一个逗号。逗号导致函数返回一个元组,而不是单个字符串。

我去掉了逗号:

def query_values(data_iterator):
    return ',\n'.join('\n({})\n'.format(',\n'.join('"{}"'.format(value) for value in data_row)
                                     ) for data_row in data_iterator
                      )

并且那个修复两个问题. 现在的输出是:

query_values:

("801",
"printer",
"barcode printer")
,

("844",
"laptop",
"windows")
,

("997",
"printer",
"barcode printer")

我加回了逗号,这样就显示出了\n。我去掉逗号后,文本又变成了多行。

我去掉了多余的\n,现在我得到了我想要的结果:

query_values:

("801","printer","barcode printer"),
("844","laptop","windows"),
("997","printer","barcode printer")

所以,我的代码可以正确运行,但我对旧版本的代码中显示的 \n 字符感到完全困惑。为什么会出现这种情况?

更新: 一些回答关注于我为什么得到一个元组,但那不是我的问题。为什么会显示 /n

4个回答

20

看起来这是元组的行为。当打印元组时,打印会在每个元素上调用__repr()__。同样适用于列表。

我尝试了这个:

tup = "xxx\nxx",
lst =["xxx\nxx"]
for t in tup,lst:
    print('t      :', t)
    for s in t:
        print('element:',s)
        print('   repr:',s.__repr__())
    print('---')

输出结果为:

t      : ('xxx\nxx',)
element: xxx
xx
   repr: 'xxx\nxx'
---
t      : ['xxx\nxx']
element: xxx
xx
   repr: 'xxx\nxx'
---

因此,元组和列表的行为相同。

当我们有一个字符串时,调用__repr__()不会展开\n字符,并在其周围加上引号:

s = "xxx\nxx"
print('s           :', s)
print('s.__repr__():', s.__repr__())

输出:

s           : xxx
xx
s.__repr__(): 'xxx\nxx'

这个元组的行为是由 running.tinterjayDaniel Roseman 在评论中提到的,但没有在答案中提到,这就是我发布这个答案的原因。


更准确地说,tuple__repr__如果未定义__str__)会在其元素上调用__repr__(https://github.com/python/cpython/blob/fc96e5474a7bda1c5dec66420e4467fc9f7ca968/Objects/tupleobject.c#L298)。 - Solomon Ucko
你是说元组没有定义__str__吗?对于一个元组t,我尝试了t.__str__(),结果和t.__repr__()一样。我不知道如何检查__str__()是否未定义或者定义为与__repr__相同。 - Granny Aching
在C代码中被标记为未定义。我认为外部看不出区别,然而。 - Solomon Ucko
1
@SolomonUcko 对于 C 类型,没有可见的区别,因为您实际上无法查找类型的“struct”中的真实属性。对于 Python 类型,有一个可见的区别。 - wizzwizz4
@wizzwizz4 是的。至少在CPython中,C类型的魔术方法显示为“slot wrapper”。 - Solomon Ucko
这些插槽包装器实际上包含了魔法,以确保任何不存在的插槽在可能的情况下被“填充”,因为无论如何都存在中间调用的开销... - wizzwizz4

12

写成 return something,return (something,) 是一样的:它返回一个包含一个元素的元组。当你使用 print 打印时,它将显示元组的外括号,并且元组中的字符串将作为其源代码表示打印出来,即带有转义码和引号。

然而,return something 只是简单地返回该值,可以正常地进行打印。


1
我知道为什么会得到一个元组。我的问题是为什么会显示\n - Granny Aching
7
@GrannyAching:你的问题在这里得到了答案。因为你打印的是字符串元组而不是单个字符串,所以会显示“\n”,而在打印元组时,这是默认行为。 - running.t
7
打印一个元组会调用repr函数来处理内部的元素。repr函数会返回对象的表示形式,通常类似于在源代码中显示的方式。因此,对于字符串来说,它将包含引号和转义字符。 - interjay

1

在Python中,元组的行为似乎是这样的。您可以通过以下简单示例进行测试:

>>> print ("xxx\n\nx",)
('xxx\n\nx',)

似乎Python能够帮助你进行调试,并在打印输出时转义所有命令序列,从而使字符串显示与其定义方式相同。但是这确实让你感到困惑,有趣的情况。 :)

0
元组可以带括号,也可以不带括号,逗号才决定了它的类型。
>>> t = 1, 'a', 'abc'
>>> type(t)
<type 'tuple'>
>>> t
(1, 'a', 'abc')
>>> 

在上述情况中,您在字符串后添加了一个逗号,Python将其解释为元组。
请查看此link
>>> t= 'a',
>>> type(t)
<type 'tuple'>
>>> t
('a',)
>>> t = 'a'
>>> type(t)
<type 'str'>
>>> t
'a'

我知道为什么我得到了一个元组。我的问题是,为什么会显示 \n - Granny Aching
2
因为在打印元组时,会对其元素调用repr函数。 - Daniel Roseman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接