Python pprint 模块

文摘   科技   2025-01-09 08:08   上海  
点击蓝字,关注山海摸鱼人

目录:

  1. pprint 模块的作用
  2. pprint.pprint() 函数
  3. pprint.pformat() 函数
  4. pprint.isreadable() 函数
  5. pprint.isrecursive() 函数
  6. pprint.saferepr() 函数
  7. 实际应用场景

pprint 模块的作用

在输出复杂的数据结构,如多层嵌套的列表、字典等,普通的 print 函数打印往往显得杂乱无章,难以清晰解读。pprint 模块(Pretty Print,美观打印)就像是一位贴心的排版大师,能够将这些复杂数据以一种整齐、易读的格式呈现出来,提升了我们对数据显示的理解效率。

在使用 pprint 模块之前,首先要将其导入到Python环境中。

import pprint

pprint.pprint() 函数

这是 pprint 模块中最常用的函数,用于以美观的格式打印数据结构。
它的基本语法是:

pprint.pprint(object, stream=None, indent=1, width=80, depth=None, *, compact=False)
  • object:类型为任意 Python 对象,是需要进行格式化打印的对象。
  • stream:类型为文件对象或 None,指定输出的目标流,默认为 None 即使用标准输出 sys.stdout
  • indent:类型为整数,用于控制打印时嵌套元素的缩进空格数量。
  • width:类型为整数,设置输出的最大宽度,超过此宽度的行将进行换行处理。
  • depth:类型为整数或 None,表示打印的嵌套深度,None 表示打印完整的嵌套结构。
  • compact:类型为布尔值,确定是否以紧凑模式输出,False 时输出更注重可读性。

示例1:打印嵌套列表

import pprint

# 定义一个嵌套列表
nested_list = [[123], [45, [678]], [910]]

# 使用 pprint 函数打印,设置缩进为 2,宽度为 30
pprint.pprint(nested_list, indent=2, width=30)

输出结果可以看到,pprint 对嵌套列表进行了合理的缩进,使层次结构一目了然。

indent 参数控制缩进的空格数,默认值是 1。通过调整这个参数,我们可以改变输出的缩进程度,使结构更清晰或更紧凑。

width 参数指定每行的最大宽度,默认值是 80。当数据长度超过这个宽度时,pprint 会自动换行。

示例2:打印字典

import pprint

my_dict = {
    "name""摸鱼",
    "age"30,
    "hobbies": ["reading""swimming""coding"]
}
pprint.pprint(my_dict, indent=2, width=50)

输出结果对于字典,pprint 会将键值对分行显示,并按照键的顺序进行排序(在Python 3.7+ 中,字典是有序的),使字典结构更清晰。

示例3:输出到文件

stream 参数指定输出的目标流,默认值是 sys.stdout,即标准输出。我们可以将其设置为其他文件对象,将格式化后的数据输出到文件中。

import pprint

data = [12345]
with open('output.txt''w'as f:
    pprint.pprint(data, stream=f)

这样,数据就会被写入到 output.txt 文件中。

pprint.pformat() 函数

pformat 函数与 pprint 函数类似,但它不直接打印数据,而是返回一个格式化后的字符串。这个字符串可以进一步用于其他操作,比如写入文件。

pformat(object, indent=1, width=80, depth=None, *, compact=False)
  • object:类型为任意 Python 对象,需要进行格式化的对象。
  • indent:类型为整数,决定缩进空格数。
  • width:类型为整数,控制输出的最大宽度。
  • depth:类型为整数或 None,指定打印的嵌套深度。
  • compact:类型为布尔值,是否采用紧凑模式。
  • 该函数的功能与 pprint 类似,但返回格式化后的字符串而不是直接打印。

示例1

import pprint

data = {
    "city""北京",
    "country""中国",
    "population"21850000
}
formatted_str = pprint.pformat(data, indent=4, width=50)
print(formatted_str)

输出结果这种方式在需要将格式化后的数据保存到文件或进行其他字符串处理时非常有用。

示例2
depth 参数控制打印的嵌套深度,默认值是 None,表示打印完整的对象。如果设置为一个整数,pprint 只会打印到指定的嵌套深度。

import pprint

data = [[[12], [34]], [[56], [78]]]
formatted_str = pprint.pformat(data, depth=2)
print(formatted_str)

输出结果可以看到,超过深度 2 的部分被显示为 ...

pprint.isreadable() 函数

isreadable 是 pprint 模块中的一个函数,其完整调用形式为 pprint.isreadable(object)

  • 参数类型object 可以是任何 Python 对象,包括列表、字典、元组、自定义对象等。
  • 函数作用:用于判断 pprint 模块是否能够将输入的对象以一种可读的方式进行格式化输出。
    它会对对象进行检查,如果对象包含不可序列化的元素(例如文件对象、网络连接对象等)或者有复杂的自定义对象没有实现适当的序列化方法时,isreadable 函数可能会返回 False,表示 pprint 不能很好地将其以可读的方式输出;
    如果对象是常规的数据结构(如普通的列表、字典、数字、字符串等),isreadable 通常会返回 True,表示 pprint 可以正常地格式化该对象。

示例代码

import pprint

# 定义一些对象
simple_list = [123]
complex_list = [12, open('test.txt''r')]  # 包含文件对象
custom_obj = object()  # 自定义对象

# 检查不同对象是否可读
print(pprint.isreadable(simple_list))
print(pprint.isreadable(complex_list))
print(pprint.isreadable(custom_obj))
  • simple_list 是一个简单的整数列表,pprint 可以很好地处理这样的对象,所以 pprint.isreadable(simple_list) 会返回 True
  • complex_list 包含一个文件对象,文件对象通常不能被 pprint 以常规方式序列化,所以 pprint.isreadable(complex_list) 会返回 False
  • custom_obj 是一个自定义对象,由于它没有实现序列化的相关方法,pprint.isreadable(custom_obj) 也会返回 False

使用场景: 在编写代码时,特别是涉及到复杂的数据结构或自定义对象时,在使用 pprint 进行格式化输出之前,可以使用 isreadable 函数进行检查,以避免出现意外的结果。
如果 isreadable 函数返回 False,你可能需要考虑自定义对象的 __repr__ 方法或使用其他方式来表示该对象,以便更好地展示其内容。

pprint.isrecursive() 函数

isrecursive 是 pprint 模块中的一个函数,其调用形式为 pprint.isrecursive(object)

  • 参数类型object 可以是任何 Python 对象,包括列表、字典、元组、自定义对象等。
  • 函数作用:用于判断输入的对象是否包含递归引用。递归引用是指一个对象直接或间接地引用了自身,例如一个列表 lst 中包含 lst 本身,或者一个对象的属性指向了该对象本身。当对象包含这样的递归引用时,isrecursive(object) 将返回 True,否则返回 False

示例代码

import pprint

# 定义一个普通的列表
normal_list = [123]
print(pprint.isrecursive(normal_list))  # 输出应为 False

# 定义一个具有递归引用的列表
recursive_list = []
recursive_list.append(recursive_list)
print(pprint.isrecursive(recursive_list))  # 输出应为 True

代码解释

  • 对于 normal_list,它是一个简单的列表,没有任何元素引用自身,因此 pprint.isrecursive(normal_list) 会输出 False
  • 对于 recursive_list,它是一个空列表,但是通过 recursive_list.append(recursive_list) 操作,它添加了自身作为元素,形成了递归引用,所以 pprint.isrecursive(recursive_list) 会输出 True

使用场景

  • 在处理复杂的数据结构,特别是可能存在递归或循环引用的数据结构时,使用 isrecursive 可以帮助你提前发现可能导致无限循环或意外结果的递归引用。例如,在使用 pprint 对数据结构进行格式化输出之前,使用 isrecursive 检查可以避免陷入无限递归,因为 pprint 可能无法处理具有递归引用的对象。
  • 在调试程序时,如果你遇到一些奇怪的输出或程序崩溃,并且怀疑可能是由于对象的递归引用导致的,可以使用 isrecursive 来检查相关对象。

pprint.saferepr() 函数

saferepr 是 pprint 模块中的一个函数,其调用形式为 pprint.saferepr(object)

  • 参数类型object 可以是任何 Python 对象,包括列表、字典、元组、自定义对象等。
  • 函数作用:该函数类似于 Python 内置的 repr() 函数,用于生成对象的字符串表示形式。然而,saferepr 函数在遇到对象中可能存在的递归引用时会进行特殊处理,避免陷入无限递归。
    当遇到递归引用的情况,saferepr 不会像 repr() 那样不断重复引用自身,而是使用特殊的表示方式来表示递归引用,通常会将递归部分表示为 <Recursion on type with id=object_id>,其中 object_id 是对象的唯一标识符。

示例代码

import pprint

# 定义一个具有递归引用的列表
recursive_list = []
recursive_list.append(recursive_list)

# 使用 saferepr 函数
print(pprint.saferepr(recursive_list))

# 对于正常对象
normal_list = [123]
print(pprint.saferepr(normal_list))

代码解释: 对于 recursive_list

  • recursive_list 是一个空列表,通过 recursive_list.append(recursive_list) 操作,它形成了递归引用,自身包含自身。
  • 使用 pprint.saferepr(recursive_list) 时,会将递归部分表示为 <Recursion on list with id=list_id>,而不是陷入无限递归。

对于 normal_list

  • 这是一个正常的列表,pprint.saferepr(normal_list) 会像 repr() 函数一样生成正常的字符串表示形式,因为没有递归引用。

使用场景

  • 在调试程序时,如果不确定对象是否包含递归引用,使用 saferepr 可以避免使用 repr() 时可能出现的无限递归错误,确保程序的正常运行。
  • 当处理可能包含复杂数据结构(如链表、树状结构等)的数据时,saferepr 可以安全地将对象转换为字符串表示,便于输出和调试,即使对象包含循环引用,也能得到有意义的表示而不是导致程序崩溃。

实际应用场景

调试代码

在调试复杂的Python程序时,pprint 模块可以帮助我们更清晰地查看变量的值。

import pprint


def complex_function():
    data = {
        "user1": {
            "name""李四",
            "age"35,
            "orders": [
                {"product""电脑""price"8000},
                {"product""手机""price"5000}
            ]
        },
        "user2": {
            "name""王五",
            "age"28,
            "orders": [
                {"product""耳机""price"300},
                {"product""鼠标""price"50}
            ]
        }
    }
    return data


result = complex_function()
pprint.pprint(result)
日志记录

在记录日志时,格式化后的数据更易于分析和排查问题。

import logging
import pprint

logging.basicConfig(filename='app.log', level=logging.INFO)

data = {
    "event""挂机登录",
    "user": {
        "name""摸鱼老六",
        "role""fisher"
    },
    "timestamp""2025-01-07 10:00:00"
}
formatted_data = pprint.pformat(data)
logging.info(formatted_data)
数据展示

在数据可视化的前期准备阶段,或者在控制台展示分析结果时,pprint 可以让数据更美观。

import numpy as np
import pprint

# 生成一些模拟数据
data = np.random.randint(110, (55))
pprint.pprint(data.tolist())

山海摸鱼人
致力于记录美好之瞬间,追寻美好之明天。
 最新文章