Python食谱-1.14.改变多行字符串的缩进

原文作者:Tom Good
中文编译:Tony (digitalsatori)

问题

有一个多行的字符串,需要创建这个字符串的一个副本,要求每行缩进相同长度的空格。

解决方法

使用字符串对象本身的方法处理这类任务就很方便,以下是我们用其构造的函数:

def reindent(s, numSpaces):
    leading_space = numSpaces * ' '
    lines = [ leading_space + line.strip( )
              for line in s.splitlines( ) ]
    return '\n'.join(lines)

讨论

当与文本打交道时,我们往往会碰到要求改变文本块的缩进程度的任务。以上的代码添加或者移除字符串每行的起始空格数,使每行的缩进程度一致:

>>> x = """  line one
...     line two
...  and line three
... """
>>> print x
  line one
    line two
 and line three
>>> print reindent(x, 4)
    line one
    line two
    and line three

有时候我们可能并不希望象上例这样使每行的缩进完全一样。比如要求给每行都增加或减少相同数量的空格,但保持各行的相对缩进。处理这类任务应该也很容易。要注意的是,在减少空格数时要检查最多能减少的空格数,以防移除了非空格字符。所以,我们将这个任务分为分别用来添加和删除空格的两个函数,和第三个函数用于计算每行的空格数并将结果以列表形式返回:

def addSpaces(s, numAdd):
    white = " " * numAdd
    return white + white.join(s.splitlines(True))
def numSpaces(s):
    return [len(line)-len(line.lstrip( )) for line in s.splitlines( )]
def delSpaces(s, numDel):
    if numDel > min(numSpaces(s)):
        raise ValueError, "removing more spaces than there are!"
    return '\n'.join([ line[numDel:] for line in s.splitlines( ) ])

所有这些函数都要依赖字符串方法: splitlines 来实现。 splitlines 与分割'\n'的 split 方法类似。但 splitlines 有一个特殊的用法,当调用该方法时,赋予其参数 True, 则会保留每行末的换行符。某些时候这种用法会非常方便。addSpaces 如果没有使用这种方法就不可能这么简洁,漂亮。

我们将上面的几个函数组合成一个新的函数,用来删除尽可能多的空格,文本块向左靠齐,同时保持各行的相对缩进:

def unIndentBlock(s):
    return delSpaces(s, min(numSpaces(s)))

参考

Python类库参考及Pyhton in a Nutshell中关于序列类型的说明。

One Response to “Python食谱-1.14.改变多行字符串的缩进”

  1. [...] Python食谱-1.14.改变多行字符串的缩进 [...]

Leave a Response