Python3标准库:textwrap文本自动换行与填充

十年热恋 提交于 2020-02-16 11:36:03

1. textwrap文本自动换行与填充

textwrap模块提供了一些快捷函数,以及可以完成所有工作的类TextWrapper。如果你只是要对一两个文本字符串进行自动或填充,快捷函数应该就够用了;否则的话,你应该使用TextWrapper的实例来提高效率。

1.1 填充段落

textwrap.fill(text,width=70,**kwargs)

  对text中的单独段落自动换行,并返回一个包含被自动换行段落的单独字符串。fill()以下语句的快捷方式。

"\n".join(wrap(text, ...))

特别要说明的是,fill()接受与wrap()完全相同的关键字参数。

import textwrap

sample_text = '''
    The textwrap module can be used to format text for output in
    situations where pretty-printing is desired.  It offers
    programmatic functionality similar to the paragraph wrapping
    or filling features found in many text editors.
    '''
print(textwrap.fill(sample_text, width=50))

结果:

结果差强人意。文本现在左对齐,不过只有第一行保留了缩进,后面各行前面的空格都嵌入到段落中。 

1.2 去除现有的缩进

textwrap.dedent(text)

  移除text中每一行的任何相同前缀空白符。

  这可以用来清除三重引号字符串行左侧空格,而仍然在源码中显示为缩进格式。

  请注意制表符和空格符都被视为是空白符,但它们并不相等:以下两行

  "  hello"和"\thello"不会被视为具有相同的前缀空白符。

  只包含空白符的行会在输入时被忽略并在输出时被标准化为单个换行符。

import textwrap

sample_text = '''
    The textwrap module can be used to format text for output in
    situations where pretty-printing is desired.  It offers
    programmatic functionality similar to the paragraph wrapping
    or filling features found in many text editors.
    '''
dedented_text = textwrap.dedent(sample_text)
print('Dedented:')
print(dedented_text)

结果:

结果看起来更好。 

由于“dedent”(去除缩进)与“indent”(缩进)正好相反,所以结果将得到一个文本块,其中每一行前面的空白符已经删除。如果一行比另一行缩进更多,有些空白符则不会被删除。  

1.3 结合dedent和fill

接下来可以把去除缩进的文本传入fill(),并指定一些不同的width值。

import textwrap

sample_text = '''
    The textwrap module can be used to format text for output in
    situations where pretty-printing is desired.  It offers
    programmatic functionality similar to the paragraph wrapping
    or filling features found in many text editors.
    '''
dedented_text = textwrap.dedent(sample_text).strip()
for width in [45, 60]:
    print('{} Columns:\n'.format(width))
    print(textwrap.fill(dedented_text, width=width))
    print()

这会生成指定宽度的输出。

 

 

1.4 缩进块

textwrap.indent(text,profix,predicate=None) 

  将prefix添加到text中选定行的开头。

  通过调用text.splitlines(True)来对行进行拆分。

  默认情况下,prefix会被添加到所有不是只由空白符(包括任何行结束符)组成的行。

  可选的predicate参数可用来控制哪些行要缩进。

  3.3新版功能。

使用>作为每一行的前缀。

import textwrap

sample_text = '''
    The textwrap module can be used to format text for output in
    situations where pretty-printing is desired.  It offers
    programmatic functionality similar to the paragraph wrapping
    or filling features found in many text editors.
    '''
dedented_text = textwrap.dedent(sample_text)
wrapped = textwrap.fill(dedented_text, width=50)
wrapped += '\n\nSecond paragraph after a blank line.'
final = textwrap.indent(wrapped, '> ')

print('Quoted block:\n')
print(final)

文本块按换行符分解,将为包含文本的各行增加前缀,然后再把这些行合并为一个新字符串并返回。

 

 

为了控制哪些行接收新前缀,可以传入一个callable对象作为indent()的predicate参数。会一次为各行文本调用这个callable,并为返回值为true的行添加前缀。

import textwrap

sample_text = '''
    The textwrap module can be used to format text for output in
    situations where pretty-printing is desired.  It offers
    programmatic functionality similar to the paragraph wrapping
    or filling features found in many text editors.
    '''
def should_indent(line):
    print('Indent {!r}?'.format(line))
    return len(line.strip()) % 2 == 0

dedented_text = textwrap.dedent(sample_text)
wrapped = textwrap.fill(dedented_text, width=50)
final = textwrap.indent(wrapped, 'EVEN ',
                        predicate=should_indent)

print('\nQuoted block:\n')
print(final)

这个例子会为包含偶数个字符的行添加前缀EVEN 。

 

 

1.5 悬挂缩进

不仅可以设置输出的宽度,还可以采用相同的方式单独控制首行的缩进,使首行的缩进不同于后续的各行。

import textwrap

sample_text = '''
    The textwrap module can be used to format text for output in
    situations where pretty-printing is desired.  It offers
    programmatic functionality similar to the paragraph wrapping
    or filling features found in many text editors.
    '''
dedented_text = textwrap.dedent(sample_text).strip()
print(textwrap.fill(dedented_text,
                    initial_indent='',
                    subsequent_indent=' ' * 4,
                    width=50,
                    ))

这就允许生成悬挂缩进,即首行缩进小于其他行的缩进。

 

 

缩进值也可以包含非空白字符。 

1.6 截断长文本

textwrap.shorten(text,width,**kwargs) 

  折叠并截断给定的text以符合给定的width。

  首先将折叠text中的空格(所有连续空格替换为单个空格)。 如果结果能适合width则将其返回。 否则将丢弃足够数量的末尾单词以使得剩余单词加placeholder能适合width。   

import textwrap

sample_text = '''
    The textwrap module can be used to format text for output in
    situations where pretty-printing is desired.  It offers
    programmatic functionality similar to the paragraph wrapping
    or filling features found in many text editors.
    '''
dedented_text = textwrap.dedent(sample_text)
original = textwrap.fill(dedented_text, width=50)

print('Original:\n')
print(original)

shortened = textwrap.shorten(original, 100)
shortened_wrapped = textwrap.fill(shortened, width=50)

print('\nShortened:\n')
print(shortened_wrapped)

如果从原文本将非空白文本作为截断部分删除,那么它会被替换为一个占位值。可以为shorten()提供参数placeholder来替代默认值[...]

 

 

1.7 TextWrapper

wrap(),fill()和shorten()的作用方式为创建一个TextWrapper实例并在其上调用单个方法。该实例不会被重用,因此对于要使用wrap()和/或fill()来处理许多文本字符串的应用来说,创建你自己的TextWrapper对象可能会更有效率。

文本最好在空白符位置自动换行,包括带连字符单词的连字符之后;长单词仅在必要时会被拆分,除非TextWrapper.break_long_words被设为假值。

class textwrap.TextWrapper(**kwargs)

TextWrapper构造器接收多个可选的关键字参数。每个关键字参数对应一个实例属性,比如说

wrapper = TextWrapper(initial_indent="* ")

就相当于

wrapper = TextWrapper()
wrapper.initial_indent = "* "

你可以多次重用相同的TextWrapper对象,并且你也可以在使用期间通过直接向实例属性赋值来修改它的任何选项。

TextWrapper的实例属性(以及构造器的关键字参数)如下所示:

width

  (默认: 70) 自动换行的最大行长度。 只要输入文本中没有长于width的单个单词,TextWrapper就能保证没有长于width个字符的输出行。

expand_tabs

  (默认: True) 如果为真值,则text中所有的制表符将使用text的expandtabs()方法扩展为空格符。

tabsize

(默认: 8) 如果expand_tabs为真值,则text中所有的制表符将扩展为零个或多个空格,具体取决于当前列位置和给定的制表宽度。

  3.3 新版功能.

replace_whitespace

  (default: True) 如果为真值,在制表符扩展之后、自动换行之前,wrap()方法将把每个空白字符都替换为单个空格。 会被替换的空白字符如下:制表,换行,垂直制表,进纸和回车 ('\t\n\v\f\r')。

注解:如果 expand_tabs 为假值且 replace_whitespace 为真值,每个制表符将被替换为单个空格,这与制表符扩展是  一样的。

注解:如果 replace_whitespace 为假值,在一行的中间有可能出现换行符并导致怪异的输出。 因此,文本应当(使用 str.splitlines() 或类似方法)拆分为段落并分别进行自动换行。

drop_whitespace

  (默认: True) 如果为真值,每一行开头和末尾的空白字符(在包装之后、缩进之前)会被丢弃。 但是段落开头的空白字符如果后面不带任何非空白字符则不会被丢弃。 如果被丢弃的空白字符占据了一个整行,则该整行将被丢弃。

initial_indent

  (默认: '') 将被添加到被自动换行输出内容的第一行的字符串。 其长度会被计入第一行的长度。 空字符串不会被缩进。

subsequent_indent

  (默认: '') 将被添加到被自动换行输出内容除第一行外的所有行的字符串。 其长度会被计入除行一行外的所有行的长度。

fix_sentence_endings

  (默认: False) 如果为真值,TextWrapper将尝试检测句子结尾并确保句子间总是以恰好两个空格符分隔。 对于使用等宽字体的文本来说通常都需要这样。 但是,句子检测算法并不完美:它假定句子结尾是一个小写字母加字符 '.''!' 或 '?' 中的一个,并可能带有字符 '"' 或 "'",最后以一个空格结束。 此算法的问题之一是它无法区分以下文本中的 "Dr."

[...] Dr. Frankenstein's monster [...]

和以下文本中的 "Spot."

[...] See Spot. See Spot run [...]

fix_sentence_endings默认为假值。

  由于句子检测算法依赖于string.lowercase来确定“小写字母”,以及约定在句点后使用两个空格来分隔处于同一行的句子,因此只适用于英语文本。

break_long_words

  (默认: True) 如果为真值,则长度超过width的单词将被分开以保证行的长度不会超过width。如果为假值,超长单词不会被分开,因而某些行的长度可能会超过width。 (超长单词将被单独作为一行,以尽量减少超出width的情况。)

break_on_hyphens

  (默认: True) 如果为真值,将根据英语的惯例首选在空白符和复合词的连字符之后自动换行。 如果为假值,则只有空白符会被视为合适的潜在断行位置,但如果你确实不希望出现分开的单词则你必须将break_long_words设为假值。 之前版本的默认行为总是允许分开带有连字符的单词。

max_lines

  (默认: None) 如果不为None,则输出内容将最多包含max_lines行,并使placeholder出现在输出内容的末尾。

  3.4 新版功能.

placeholder

  (默认: [...]') 该文本将在输出文本被截短时出现在文本末尾。

  3.4 新版功能.

TextWrapper还提供了一些公有方法,类似于模块层级的便捷函数:

wrap(text)

  对text(字符串) 中的单独段落自动换行以使每行长度最多为width个字符。 所有自动换行选项均获取自TextWrapper实例的实例属性。 返回由输出行组成的列表,行尾不带换行符。 如果自动换行输出结果没有任何内容,则返回空列表。

fill(text)

  对text中的单独段落自动换行并返回包含被自动换行段落的单独字符串。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!