目录:
pprint
模块的作用pprint.pprint()
函数pprint.pformat()
函数pprint.isreadable()
函数pprint.isrecursive()
函数pprint.saferepr()
函数实际应用场景
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 = [[1, 2, 3], [4, 5, [6, 7, 8]], [9, 10]]
# 使用 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 = [1, 2, 3, 4, 5]
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)
输出结果:这种方式在需要将格式化后的数据保存到文件或进行其他字符串处理时非常有用。
示例2depth
参数控制打印的嵌套深度,默认值是 None
,表示打印完整的对象。如果设置为一个整数,pprint
只会打印到指定的嵌套深度。
import pprint
data = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
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 = [1, 2, 3]
complex_list = [1, 2, 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 = [1, 2, 3]
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 = [1, 2, 3]
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(1, 10, (5, 5))
pprint.pprint(data.tolist())