Python中打印对象所有属性和值的方法探讨

Python中打印对象所有属性和值的方法探讨

技术背景

在Python编程中,有时我们需要查看一个对象的所有属性和对应的值,以便于调试代码、理解对象的结构。然而,Python并没有一个直接的内置函数可以完美地实现这一需求,不过我们可以通过一些内置函数和模块来组合实现。

实现步骤

1. 使用vars()pprint()组合

vars()函数可以返回对象的属性和属性值的字典,pprint()可以将字典以更美观的格式打印出来。

1
2
3
4
5
6
7
8
9
from pprint import pprint

# 示例对象
class O:
def __init__(self):
self.value = 3

o = O()
pprint(vars(o))

2. 使用dir()__dict__

dir()函数可以返回对象的所有属性名,__dict__可以获取对象的属性和属性值的字典。

1
2
3
4
5
6
7
8
9
class O:
def __init__(self):
self.value = 3

o = O()
l = dir(o)
d = o.__dict__
print(l)
pprint(d)

3. 自定义函数实现

可以自定义函数来过滤不需要的属性,如方法和非公共API部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from pprint import pprint
from inspect import getmembers
from types import FunctionType

def attributes(obj):
disallowed_names = {
name for name, value in getmembers(type(obj))
if isinstance(value, FunctionType)
}
return {
name: getattr(obj, name) for name in dir(obj)
if name[0] != '_' and name not in disallowed_names and hasattr(obj, name)
}

def print_attributes(obj):
pprint(attributes(obj))

class O:
def __init__(self):
self.value = 3

o = O()
print_attributes(o)

核心代码

以下是一个综合的自定义函数,用于打印对象的所有属性和值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from pprint import pprint
from inspect import getmembers
from types import FunctionType

def attributes(obj):
disallowed_names = {
name for name, value in getmembers(type(obj))
if isinstance(value, FunctionType)
}
return {
name: getattr(obj, name) for name in dir(obj)
if name[0] != '_' and name not in disallowed_names and hasattr(obj, name)
}

def print_attributes(obj):
pprint(attributes(obj))

最佳实践

使用@dataclasspprint

在Python 3.10及以上版本中,可以使用@dataclasspprint来递归、缩进地打印对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from dataclasses import dataclass
from pprint import pprint

@dataclass
class MyClass1:
s: str
n0: int
n1: int
n2: int
n3: int
n4: int
n5: int
n6: int
n7: int
n8: int
n9: int

@dataclass
class MyClass2:
s: str
n0: int
n1: int
n2: int
n3: int
n4: int
n5: int
n6: int
n7: int
n8: int
n9: int
my_class_1: MyClass1

obj = MyClass2(s='a', n0=0, n1=1, n2=2, n3=3, n4=4, n5=5, n6=6, n7=7, n8=8, n9=9, my_class_1=MyClass1(s='a', n0=0, n1=1, n2=2, n3=3, n4=4, n5=5, n6=6, n7=7, n8=8, n9=9))
pprint(obj)

常见问题

1. vars()函数报错

vars()函数要求对象必须有__dict__属性,否则会抛出TypeError异常。

1
2
3
4
5
6
# 示例报错代码
a = 1
try:
pprint(vars(a))
except TypeError as e:
print(f"Error: {e}")

2. dir()只返回属性名

dir()函数只会返回对象的属性名,如果需要属性值,还需要结合getattr()函数。

1
2
3
4
5
6
7
8
9
class O:
def __init__(self):
self.value = 3

o = O()
attr_names = dir(o)
for name in attr_names:
value = getattr(o, name)
print(f"{name}: {value}")

3. 部分属性无法访问

有些对象的属性可能由于权限或实现问题无法访问,此时可以使用异常处理来跳过这些属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import warnings

def dump(obj):
for name in dir(obj):
e = False
with warnings.catch_warnings():
warnings.simplefilter("ignore")
try:
v = getattr(obj, name)
except:
e = True
warnings.simplefilter("default")
if not e:
print(f"obj.{name} = {v!r}")
else:
print(f"<inaccessible property obj.{name}>")

class O:
def __init__(self):
self.value = 3

o = O()
dump(o)

Python中打印对象所有属性和值的方法探讨
https://119291.xyz/posts/python-object-attributes-printing/
作者
ww
发布于
2025年6月3日
许可协议