python输入多行字符串_python多行字符串的正确缩进

函数中python多行字符串的正确缩进是什么?

1

2

3

4def method():

string ="""line one

line two

line three"""

1

2

3

4def method():

string ="""line one

line two

line three"""

或者别的什么?

在第一个示例中,字符串挂在函数外部看起来有点奇怪。

docstring被特殊处理:第一行的任何缩进都被删除;所有其他非空白行的最小公共缩进都被删除。除此之外,不幸的是,python中的多行字符串文本是从空白中得到的:字符串分隔符之间的所有字符都成为字符串的一部分,包括使用python读取本能的缩进,看起来应该从文本开始的行的缩进中测量。

你可能想和"""排成一队

1

2

3

4def foo():

string ="""line one

line two

line three"""

由于换行符和空格包含在字符串本身中,因此必须对其进行后处理。如果您不想这样做,并且有大量的文本,那么您可能需要将其单独存储在一个文本文件中。如果一个文本文件对您的应用程序不起作用,并且您不想进行后处理,我可能会选择

1

2

3

4def foo():

string = ("this is an"

"implicitly joined"

"string")

如果要对多行字符串进行后处理,以消除不需要的部分,则应考虑textwrap模块或PEP 257中介绍的后处理docstrings的技术:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25def trim(docstring):

if not docstring:

return ''

# Convert tabs to spaces (following the normal Python rules)

# and split into a list of lines:

lines = docstring.expandtabs().splitlines()

# Determine minimum indentation (first line doesn't count):

indent = sys.maxint

for line in lines[1:]:

stripped = line.lstrip()

if stripped:

indent = min(indent, len(line) - len(stripped))

# Remove indentation (first line is special):

trimmed = [lines[0].strip()]

if indent < sys.maxint:

for line in lines[1:]:

trimmed.append(line[indent:].rstrip())

# Strip off trailing and leading blank lines:

while trimmed and not trimmed[-1]:

trimmed.pop()

while trimmed and not trimmed[0]:

trimmed.pop(0)

# Return a single string:

return '

'.join(trimmed)

对于字符串中的每一行文本,具有相同的缩进级别是很好的。但这意味着文本行应该是(4列)中的一个缩进级别,而不是从上一行的任意多列开始。

@Bignose,我不明白这一需求如何帮助保持代码的整洁、可读性或具有任何特殊的优势。

这是连续行的"挂起缩进"样式。在PEP8中,它是为函数定义和长if语句等目的而规定的,但没有为多行字符串提到。就我个人而言,这是一个我拒绝遵循PEP8的地方(而是使用4空间缩进),因为我非常不喜欢悬挂缩进,这对我来说模糊了程序的正确结构。

@Mike描述的字符串的用法在哪里?string="(这是一个""隐式联接""string")。

@缓冲区,在官方教程的3.1.2中("两个相邻的字符串将自动连接…")和语言引用中。

带有自动字符串连接的第二个表单不包含换行符,因此需要为每行添加。这种方法插入空行也是非常不自然的(您需要有""行)。我希望有类似于bash的here文档的支持,禁止使用前导标签(

第二个具有自动字符串连接的表单不包含换行符,这是一个特性。

另请参见"是否认为隐式字符串文字串联有害?"作者:guido van rossum(某个随机的家伙…)lwn.net/articles/551426

值得注意的是,虽然隐式连接是Python最好不具备的一种错误功能,但是这种特殊的使用并不特别难理解,也不特别容易出错。

+1对于("this is an"…技术。它作为docstring工作。如果需要换行,可以使用("this is an" "

"。

PEP257中规定的trim()功能在标准库中实现,称为inspect.cleandoc。

我发现第二个例子要在python 3中工作,我还必须添加尾随到行尾。否则我会得到"意外的缩进"错误。

@Mrtj它在python 3中对我有用——你有帕伦斯吗?

啊,我忽略了括号,对不起!

+1对@bobince关于拒绝"悬挂缩进"的评论…特别是因为如果您将变量名从string更改为text或任何不同长度的内容,那么现在您需要更新多行字符串中每一行的缩进,以使其与"""正确匹配。缩进策略不应该使未来的重构/维护复杂化,而且它是PEP真正失败的地方之一。

textwrap.dedent函数允许您从源文件中正确的缩进开始,然后在使用前将其从文本中删除。

正如其他一些人所指出的,权衡是,这是对文本的额外函数调用;在决定将这些文本放在代码中的位置时,要考虑到这一点。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17import textwrap

def frobnicate(param):

""" Frobnicate the scrognate param.

The Weebly-Ruckford algorithm is employed to frobnicate

the scrognate to within an inch of its life.

"""

prepare_the_comfy_chair(param)

log_message = textwrap.dedent("""\

Prepare to frobnicate:

Here it comes...

Any moment now.

And: Frobnicate!""")

weebly(param, log_message)

ruckford(param)

日志消息文本中的尾随\用于确保换行符不在文本中;这样,文本就不会以空行开头,而是以下一整行开头。

EDOCX1的返回值(0)是输入字符串,在该字符串的每一行上删除所有常见的前导空格缩进。因此,上述log_message值为:

1

2

3

4Prepare to frobnicate:

Here it comes...

Any moment now.

And: Frobnicate!

虽然这是一个合理的解决方案,而且很容易知道,但是在一个经常调用的函数中执行这样的操作可能会被证明是一个灾难。

@Haridsv为什么会是一场灾难?

@jtmoulia:比灾难更好的描述是"低效的",因为textwrap.dedent()调用的结果是一个常量值,就像它的输入参数一样。

@haridsv这种灾难/低效的根源是在一个经常被调用的函数中定义一个常量字符串。可以为每次调用查找交换每次调用常量定义。这样,DEDENT预处理将只运行一次。相关的问题可能是stackoverflow.com/q/15495376/611007,它列出了避免每次调用定义常量的想法。尽管替代方案似乎需要查找。尽管如此,人们还是尝试了各种方法来寻找合适的存放地点。例如:def foo: return foo.x,然后是下一行foo.x = textwrap.dedent("bar")。

我想,如果字符串只用于在调试模式下启用的日志记录,而不用于其他模式,那么效率会很低。但是为什么还要记录多行字符串呢?因此,很难找到一个实际的例子,上面提到的效率低下(也就是说,它大大降低了程序的速度),因为任何消耗这些字符串的东西都会变慢。

我想知道更多关于这个小的Ruckford算法,听起来很有趣…有趣。

其他答案中似乎缺少的一个选项(仅在NAXA的评论中深入提到)是:

1

2

3

4

5

6

7

8

9def foo():

string = ("line one

" # Add

in the string

"line two" "

" # Add"

" after the string

"line three

")

这将允许适当的对齐,隐式连接行,并且仍然保持行移动,对我来说,这是我为什么无论如何都要使用多行字符串的原因之一。

它不需要任何后处理,但您需要在希望行结束的任何给定位置手动添加。可以是内联的,也可以是后面的单独字符串。后者更容易复制粘贴。

请注意,这是一个隐式联接字符串的示例,而不是多行字符串。

@trk,从字串包含换行(也就是多行)的意义上说,它是多行的,但是它使用join来规避op的格式问题。

使用inspect.cleandoc如下:

1

2

3

4

5def method():

string = inspect.cleandoc("""

line one

line two

line three""")

将按预期保持相对压痕。

Note: It's good practice to indent logical blocks of code under its related context to clarify the structure. E.g. the multi-line string belonging to the variable string.

很困惑为什么这个答案直到现在才存在,从2008年的python 2.6开始,inspect.cleandoc就一直存在。绝对是最干净的答案,尤其是因为它不使用悬挂缩进样式,这只会浪费不必要的空间。

还有一些选择。在启用了pylab的ipython中,dedent已经在命名空间中。我查过了,是从Matplotlib寄来的。也可以通过以下方式导入:

1from matplotlib.cbook import dedent

在文档中,它声明它比textwarp等价的快,在我的ipython测试中,它比我的快速测试平均快3倍。它还有一个好处,那就是它丢弃了任何前导空白行,这使您能够灵活地构造字符串:

1

2

3

4

5

6

7

8

9

10

11

12

13"""

line 1 of string

line 2 of string

"""

"""\

line 1 of string

line 2 of string

"""

"""line 1 of string

line 2 of string

"""

利用这三个例子中的matplotlib,将得到同样合理的结果。textwarp dedent函数将在第一个示例中有一个前导空白行。

明显的缺点是,文本包装在标准库中,而matplotlib是外部模块。

这里有些折衷…DEDENT函数使您的代码在定义字符串的地方更易于阅读,但需要稍后进行处理才能获得可用格式的字符串。在docstring中,很明显您应该使用正确的缩进,因为大多数docstring的使用都会进行所需的处理。

当我在代码中需要一个非长字符串时,我会发现下面的代码确实很难看,我让长字符串从封闭的缩进中退出。当然,在"美丽胜于丑陋"这一问题上失败了,但有人可能会说,它比"丑陋"的选择更简单、更明确。

1

2

3

4

5

6

7

8

9

10def example():

long_string = '''\

Lorem ipsum dolor sit amet, consectetur adipisicing

elit, sed do eiusmod tempor incididunt ut labore et

dolore magna aliqua. Ut enim ad minim veniam, quis

nostrud exercitation ullamco laboris nisi ut aliquip.\

'''

return long_string

print example()

如果您想要一个快速简单的解决方案并避免自己键入新行,您可以选择一个列表,例如:

1

2

3

4

5

6

7

8

9

10def func(*args, **kwargs):

string = '

'.join([

'first line of very long string and',

'second line of the same long thing and',

'third line of ...',

'and so on...',

])

print(string)

return

虽然这不是最好的方法,但我经常使用它。如果确实使用了它,那么应该使用元组而不是列表,因为在联接之前不会修改它。

我更喜欢

1

2

3

4

5

6

7def method():

string = \

"""\

line one

line two

line three\

"""

1

2

3

4

5

6def method():

string ="""\

line one

line two

line three\

"""

这并不能回答这个问题,因为这个问题明确地说明了缩进(在函数中)很重要。

@大鼻子这个问题说"看起来有点奇怪"不允许使用。

如果没有难看的凹痕,我该怎么做呢?

@lfender6445好吧,也许你可以把所有这些字符串和其他代码放在一个单独的文件中…

我的两分钱,从行尾逃出去拿缩进:

1

2

3

4

5

6

7def foo():

return"{}

"\

"freq: {}

"\

"temp: {}

".format( time, freq, temp )

第一个选项是好的-包括缩进。它是Python风格的-为代码提供可读性。

要正确显示:

1print string.lstrip()

这似乎是格式化三引号字符串的最简单、最干净的方法,这样您就不会因为缩进而有多余的空格。

这将只删除多行字符串第一行中的前导空格。它对格式化以下行没有帮助。

我来这里是想找一个简单的1行程序来删除/更正要打印的docstring的标识级别,而不会使它看起来不整洁,例如,通过在脚本中使其"挂起在函数之外"。

我最后做的是:

1

2

3

4

5

6

7

8

9

10

11import string

def myfunction():

"""

line 1 of docstring

line 2 of docstring

line 3 of docstring"""

print str(string.replace(myfunction.__doc__,'

\t','

'))[1:]

显然,如果使用空格(例如4)而不是制表键进行缩进,请使用类似这样的内容:

1

2

3print str(string.replace(myfunction.__doc__,'

','

'))[1:]

如果您希望DocStrings看起来像这样,则无需删除第一个字符:

1

2

3

4

5

6

7"""line 1 of docstring

line 2 of docstring

line 3 of docstring"""

print string.replace(myfunction.__doc__,'

\t','

')

这在类方法和嵌套类上失败。

对于字符串,您可以在处理完字符串之后进行处理。对于docstrings,您需要在处理完函数之后进行处理。这是一个仍然可读的解决方案。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40class Lstrip(object):

def __rsub__(self, other):

import re

return re.sub('^

', '', re.sub('

$', '', re.sub('

\s+', '

', other)))

msg = '''

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod

tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim

veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea

commodo consequat. Duis aute irure dolor in reprehenderit in voluptate

velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat

cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id

est laborum.

''' - Lstrip()

print msg

def lstrip_docstring(func):

func.__doc__ = func.__doc__ - Lstrip()

return func

@lstrip_docstring

def foo():

'''

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod

tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim

veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea

commodo consequat. Duis aute irure dolor in reprehenderit in voluptate

velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat

cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id

est laborum.

'''

pass

print foo.__doc__

处理文档字符串必须已经处理一致的缩进,如PEP257所述。已经有了一些工具,例如inspect.cleandoc,它们可以以正确的方式实现这一点。

这取决于文本的显示方式。如果您希望所有的代码都保持对齐,那么要么将其格式化为第一个代码段中的格式,要么遍历左侧的行,修剪所有的空间。

docstring处理工具的工作方式不是删除左边的所有空间,而是删除第一行缩进的空间。这个策略有点复杂,允许您缩进并在后处理字符串中考虑它。

我有时会将多行文本作为字符串列表写入,然后将它们连接起来…

1

2

3

4

5

6part ="".join([

"\x00\x00\x00\x00\x0C\x00\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00"

"\x00\x00\x00\x00\x0C\x00\x00\x00\x00\xFF\x00\x00\x00\x00\x00\x00",

"\x00\x00\x00\x00\x0C\x00\x00\x00\x00\x00\xFF\x00\x00\x00\x00\x00",

"\x00\x00\x00\x00\x0C\x00\x00\x00\x00\x00\x00\xFF\x00\x00\x00\x00",

])

这不是最有效的方法,但是对于大多数用例来说,它的性能已经足够好了,而且它不会干扰您的缩进,也不会要求第一行具有与第二行不同的缩进,就像三重引用方法一样。

虽然这可能会回答作者的问题,但它缺少一些解释性的词汇和到文档的链接。如果没有周围的短语,原始代码片段并不是很有用。你也会发现如何写一个好的答案非常有帮助。请编辑您的答案。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值