【问题标题】:Python: Indent all lines of a string except first while preserving linebreaks?Python:在保留换行符的同时缩进字符串的所有行,除了第一行?
【发布时间】:2013-09-02 07:19:26
【问题描述】:

我想缩进除第一行之外的多行字符串的所有行,但不换行。

比如我想转:

A very very very very very very very very very very very very very very very very
long mutiline
string

进入:

A very very very very very very very very very very very very very very very very
     long multiline
     string

我试过了

textwrap.fill(string, width=999999999999, subsequent_indent='   ',)

但这仍然将所有文本放在一行上。想法?

【问题讨论】:

  • 来自subsequent_indent 的文档:“将添加到所有包装输出行的字符串。”由于没有任何内容被包装,因此没有任何内容被缩进。

标签: python string text indentation word-wrap


【解决方案1】:

您只需将换行符'\n' 替换为换行符加上空格 '\n    ' 并将其保存到变量中(因为replace 不会更改您的原始字符串,而是返回一个新字符串与替换)。

string = string.replace('\n', '\n    ')

【讨论】:

    【解决方案2】:

    你的意思是这样的:

    In [21]: s = 'abc\ndef\nxyz'
    
    In [22]: print s
    abc
    def
    xyz
    
    In [23]: print '\n    '.join(s.split('\n'))
    abc
        def
        xyz
    

    ?

    编辑: 或者(HT @Steven Rumbalski):

    In [24]: print s.replace('\n', '\n    ')
    abc
        def
        xyz
    

    【讨论】:

    • 为什么splitjoin 可以简单地使用replace
    • @DavidY.Stephenson:将textwrap 用于不需要任何包装的工作似乎很不合时宜。
    【解决方案3】:

    @steven-rumbalski 提到的裸替换将是实现此目的最有效的方法,但它不是唯一的方法。

    这是另一个使用列表推导的解决方案。如果文本已经被分割成行列表,这将比运行join()replace()splitlines() 快​​得多

    text = """A very very very very very very very very very very very very very very very very
    long mutiline
    string"""
    
    lines = text.splitlines()
    indented = ['    ' + l for l in lines]
    indented[0] = lines[0]
    indented = '\n'.join(indented)
    

    可以就地修改列表,但与使用第二个变量相比,性能成本很高。缩进所有行然后在另一个操作中换出第一行也比较快。

    还有textwrap 模块。我不同意使用 textwrap 进行缩进是 unpythonic 的。如果这些行连接在一个包含换行符的字符串中,则该字符串本质上是换行的。缩进是文本换行的逻辑扩展,所以 textwrap 对我来说很有意义。

    除了它很慢。真的,真的很慢。就像慢了 15 倍。

    Python 3 将indent 添加到textwrap,这使得无需重新包装的缩进变得非常容易。当然有一种更优雅的方式来处理 lambda 谓词,但这正是原始问题所要求的。

    indented = textwrap.indent(text, '    ', lambda x: not text.splitlines()[0] in x )
    

    这里有一些timeit 各种方法的结果。

    >>> timeit.timeit(r"text.replace('\n', '\n    ')", setup='text = """%s"""' % text)
    0.5123521030182019
    

    两种列表理解解决方案:

    >>> timeit.timeit(r"indented = ['    ' + i for i in lines]; indented[0] = lines[0]", setup='lines = """%s""".splitlines()' % text)
    0.7037646849639714
    
    >>> timeit.timeit(r"indented = [lines[0]] + ['    ' + i for i in lines[1:]]", setup='lines = """%s""".splitlines()' % text)
    1.0310905870283023
    

    这是不幸的textwrap 结果:

    >>> timeit.timeit(r"textwrap.indent(text, '    ', lambda x: not text.splitlines()[0] in x )", setup='import textwrap; text = """%s"""' % text)
    7.7950868209591135
    

    我认为其中一些时间可能是非常低效的谓词,但即使将其删除,textwrap.indent 仍然比裸替换慢 8 倍以上。

    >>> timeit.timeit(r"textwrap.indent(text, '    ')", setup='import textwrap; text = """%s"""' % text)
    4.266149697010405
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-05
      • 1970-01-01
      • 1970-01-01
      • 2013-03-07
      • 2015-03-21
      • 1970-01-01
      • 1970-01-01
      • 2018-08-21
      相关资源
      最近更新 更多