ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Python面向对象:__str__与__repr__打印对象格式

Python面向对象:__str__与__repr__打印对象格式 Python面向对象__str__与__repr__打印对象格式一、开篇你的对象打印出来好看吗当你print(obj)时Python内部调用了什么为什么有时输出__main__.MyClass object at 0x7f...这种让人抓狂的格式有时又很友好⌨️ 答案在两个魔法方法中classProduct:def__init__(self,name,price):self.namename self.priceprice# 默认输出——毫无信息量pProduct(机械键盘,399)print(p)# __main__.Product object at 0x7f8b...print(repr(p))# __main__.Product object at 0x7f8b...# ✅ 定义了__str__和__repr__之后classProductV2:def__init__(self,name,price):self.namename self.pricepricedef__str__(self):给用户看的——友好、可读returnf{self.name}¥{self.price}def__repr__(self):给开发者看的——精确、可复现returnfProductV2(name{self.name}, price{self.price})p2ProductV2(机械键盘,399)print(p2)# 机械键盘¥399 —— __str__print(repr(p2))# ProductV2(name机械键盘, price399) —— __repr__# 在交互环境中直接输入p2# p2# ProductV2(name机械键盘, price399) —— 交互环境用__repr__ 简单记忆__str__是给用户看的print()__repr__是给开发者看的调试、交互环境。前者追求可读后者追求精确和无歧义。二、str用户友好的字符串2.1 何时被调用classBook:def__init__(self,title,author,pages):self.titletitle self.authorauthor self.pagespagesdef__str__(self):returnf《{self.title}》作者{self.author}{self.pages}页bookBook(Python编程,张三,500)# __str__在这些情况下被调用print(book)# 1. print()print(str(book))# 2. str()print(f我正在读{book})# 3. f-string格式化print(书籍信息%s%book)# 4. %s格式化print(书籍信息{}.format(book))# 5. format()# 如果只定义了__str__没有__repr__# print(book) 正常调用__str__# repr(book) 会退回到默认的 __main__.Book object at ...2.2 设计好的__str__fromdatetimeimportdatetimeclassOrder:订单类——设计清晰的__str__def__init__(self,order_id,customer,items,created_atNone):self.order_idorder_id self.customercustomer self.itemsitems# list of (name, quantity, price)self.created_atcreated_atordatetime.now()def__str__(self):lines[f订单 #{self.order_id},f客户:{self.customer},f时间:{self.created_at.strftime(%Y-%m-%d %H:%M)},-*40,]total0forname,qty,priceinself.items:subtotalqty*price totalsubtotal lines.append(f{name}×{qty}¥{price} ¥{subtotal})lines.append(-*40)lines.append(f合计: ¥{total})return\n.join(lines)orderOrder(ORD-2024001,张三,[(机械键盘,1,399),(鼠标,2,199),(鼠标垫,3,29),])print(order)三、repr开发者的精确表示3.1 黄金法则# __repr__的黄金法则来自官方文档# 如果可能__repr__应该返回一个字符串# 用这个字符串可以通过eval()重新创建相同值的对象classPoint:def__init__(self,x,y):self.xx self.yydef__repr__(self):# 返回的字符串可以直接用来重新创建对象returnfPoint(x{self.x}, y{self.y})def__str__(self):returnf({self.x},{self.y})pPoint(3,4)print(repr(p))# Point(x3, y4)# 验证黄金法则importast# p2 eval(repr(p)) # 重新创建了一个Point对象# print(p2.x, p2.y) # 3 4# ⚠️ 但不是所有对象都能这样还原# 对于复杂对象数据库连接、文件句柄等# __repr__至少应该明确描述对象3.2 __repr__在调试中的作用# 列表、字典中的对象显示用的是__repr__classStudent:def__init__(self,name,score):self.namename self.scorescoredef__repr__(self):returnfStudent({self.name!r},{self.score})# !r表示对name调用repr()——显示带引号的字符串def__str__(self):returnf{self.name}({self.score}分)students[Student(张三,85),Student(李四,92),Student(王五,78),]# 在列表/字典中——用__repr__print(students)# [Student(张三, 85), Student(李四, 92), Student(王五, 78)]# 调试时信息量十足# 在logging中——用__repr__importlogging logging.basicConfig(levellogging.DEBUG)# logging.debug(学生列表: %r, students) # %r 调用__repr__四、两者对比和交互4.1 优先级规则classDemo:def__str__(self):return这是__str__def__repr__(self):return这是__repr__dDemo()# 各种场景的调用print(d)# __str__ —— print()优先使用__str__print(str(d))# __str__print(repr(d))# __repr__print(f{d})# __str__ —— f-string默认用__str__print(f{d!r})# __repr__ —— !r强制用__repr__print(f{d!s})# __str__ —— !s强制用__str__# 只有__repr__没有__str__时classOnlyRepr:def__repr__(self):returnOnlyRepr实例or_objOnlyRepr()print(or_obj)# OnlyRepr实例 —— print()回退到__repr__print(str(or_obj))# OnlyRepr实例 —— str()也回退到__repr__4.2 标准做法# ✅ 最佳实践至少定义__repr__# 如果只能定义一个选择__repr__——它是__str__的后备classCard:扑克牌SUITS{S:♠,H:♥,D:♦,C:♣}RANKS{1:A,11:J,12:Q,13:K}def__init__(self,suit,rank):self.suitsuit self.rankrankdef__repr__(self):精确表示——用于调试returnfCard(suit{self.suit}, rank{self.rank})def__str__(self):友好显示——给用户看suit_symbolself.SUITS.get(self.suit,self.suit)rank_symbolself.RANKS.get(self.rank,str(self.rank))returnf{suit_symbol}{rank_symbol}# 测试cardCard(S,1)# 黑桃Aprint(card)# ♠Aprint(repr(card))# Card(suitS, rank1)# 在列表中hand[Card(S,1),Card(H,13),Card(D,11)]print(hand)# [Card(suitS, rank1), Card(suitH, rank13), Card(suitD, rank11)]五、总结__str__和__repr__是Python对象的名片。前者面向用户可读后者面向开发者精确。核心规则方法用途调用方式优先级__str__用户友好print(),str(),f{obj}高print优先用__repr__开发者精确repr(),f{obj!r}, 交互环境低str回退到它✅黄金法则__repr__返回的字符串应尽量能用eval()重建对象。至少定义__repr__——这样print()也能用。如果需要友好格式再叠加__str__。
返回列表