Python 打印对象为啥输出 <__main__.XXX object at 0x…>?彻底搞懂对象打印原理

11次阅读
没有评论

很多初学 Python 的小伙伴都遇到过这个尴尬问题:自己定义了一个类,实例化对象后直接 print() 打印,没有输出想要的内容,反而跳出一串莫名其妙的字符串,类似 <__main__.User object at 0x7f8b12345678>

这到底是什么意思?为什么不能直接打印对象数据?怎么才能让打印对象输出自定义内容?今天这篇文章一次性讲透 Python 打印 object 的底层逻辑,看完彻底告别打印对象看不懂的问题!

一、先复现问题:默认打印对象的效果

我们先写一段最简单的自定义类代码,看看原生的打印效果:

# 自定义一个学生类
class Student:
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score

# 实例化对象
stu = Student("小明", 18, 95)

# 直接打印对象
print(stu)

输出结果:

<__main__.Student object at 0x7fa23d5c9820>

这串字符由三部分组成:

  • __main__.Student:对象所属的类名,__main__ 代表当前运行的脚本模块
  • object:标识这是一个 Python 对象
  • 0x7fa23d5c9820:对象在内存中的十六进制地址

简单来说:Python 默认不知道你想展示对象的哪个数据,所以只能打印对象的身份信息(类+内存地址)

二、底层原理:Python 打印对象的执行逻辑

在 Python 中,所有类都默认继承顶层父类 object,而 object 自带两个核心方法,控制着对象的打印和展示效果:__str____repr__

当我们执行 print(对象) 时,Python 会优先执行这套逻辑:

  1. 优先调用对象的 __str__() 方法,获取字符串结果并打印;
  2. 如果没有定义 __str__(),则调用 __repr__() 方法;
  3. 如果两个方法都没重写,就会调用 object 父类的默认方法,输出我们看到的内存地址格式字符串。

这就是默认打印结果晦涩难懂的根本原因:父类的默认方法只输出对象身份,不输出自定义属性

三、自定义打印:重写 __str__ 方法(日常首选)

__str__() 是给用户看的友好字符串,也是日常打印对象最常用的重写方法,优先级最高。我们只需要在类中重写这个方法,返回自定义的展示字符串,就能实现优雅打印。

改造上面的学生类:

class Student:
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score

    # 重写__str__方法,自定义打印格式
    def __str__(self):
        # 返回想要展示的对象信息
        return f"学生信息:姓名={self.name},年龄={self.age},分数={self.score}"

stu = Student("小明", 18, 95)
print(stu)

输出结果(清晰易懂):

学生信息:姓名=小明,年龄=18,分数=95

✅ 核心规则:__str__()必须返回字符串类型,不能直接 print,否则会报错。

四、进阶补充:重写 __repr__ 方法(开发调试首选)

很多小伙伴会疑惑两个方法的区别,这里直白区分:

  • __str__:面向普通用户,追求简洁易懂,用于日常打印输出;
  • __repr__:面向开发者,追求精准、完整,用于调试、日志、交互式终端展示。

如果只定义 __repr__,不定义 __str__,print 对象时会自动调用 __repr__。开发中建议 优先重写 __repr__,兼容性更强。

示例代码:

class Student:
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score

    # 调试风格的对象展示
    def __repr__(self):
        return f"Student(name='{self.name}', age={self.age}, score={self.score})"

stu = Student("小明", 18, 95)
print(stu)
# 终端直接输入对象回车,也会触发__repr__
stu

输出结果:

Student(name='小明', age=18, score=95)

五、懒人技巧:一键打印对象所有属性

如果对象属性很多,一个个拼接字符串太麻烦,推荐两个懒人通用方法,无需手动拼接:

方法1:使用 __dict__ 打印所有属性

Python 对象的 __dict__ 属性会存储对象所有自定义属性和值,直接打印即可:

class Student:
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score

stu = Student("小明", 18, 95)
print(stu.__dict__)

输出:{'name': '小明', 'age': 18, 'score': 95}

方法2:封装通用打印方法(所有类通用)

def print_obj(obj):
    print(f"【{type(obj).__name__}对象信息】")
    for k, v in obj.__dict__.items():
        print(f"{k}: {v}")

# 调用
print_obj(stu)

六、高频面试/笔试考点总结

  1. 默认打印对象输出 xxx object at 0x... 的原因:未重写 __str____repr__,调用了 object 父类默认方法;
  2. print(对象) 优先调用 __str__,次选 __repr__
  3. __str__ 面向用户,__repr__ 面向开发者调试;
  4. 两个方法都必须返回字符串,不能直接打印。

七、最后总结

Python 打印对象看不懂,根本不是代码 bug,只是缺少自定义的对象展示规则

  • 日常业务输出:重写__str__,简洁友好;
  • 开发调试排查:重写 __repr__,精准规范;
  • 快速查看属性:直接使用 __dict__,高效便捷。

掌握这几个用法,彻底解决 Python 对象打印晦涩的问题,代码可读性直接拉满!

正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 0
评论(没有评论)
验证码