网易首页 > 网易号 > 正文 申请入驻

可以格式化Python自定义对象的3个魔术方法

0
分享至

在Python中,下划线用于属性名时具有特殊含义。一种特殊形式是使用两对双下划线,一个在属性名之前,另一个在属性名之后,这被称为特殊方法或魔术方法。

例如,我们大多数人知道的第一个特殊方法可能是初始化方法__init__,它用于创建Python对象。下面的代码显示了一个示例:

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

当你创建这个类的实例对象时,你可以通过在交互式控制台中输入对象变量来检查这个对象:

>>> student0 = Student("John Smith")
>>> student0
<__main__.Student at 0x11883aa60>

然而,这个对象的信息并不是很友好,它只是显示了它的类和内存地址。为了使它更有趣,我们应该考虑定制类的字符串格式化方法。具体来说,我们将在本文中讨论三种特殊的方法。

repr方法

__repr__方法与对象的表示相关,将对象转化为供解释器读取的形式。如上所示,Python对象在交互式控制台中输出其表示字符串。下面的代码显示了这个特性:

>>> class Student:
... def __init__(self, name):
... self.name = name
...
... def __repr__(self):
... return "__repr__ is called"
...
>>> student0 = Student("John Smith")
>>> student0
__repr__ is called

需要注意的一点是,我们应该为__repr__特殊方法返回一个字符串。如果返回一个非字符串,就会遇到TypeError,如下图所示。

但是尚未解决的问题是,我们应该为对象返回什么字符串?根据经验来说,我们应该返回一个字符串,用户可以使用它重新构造对象(例如,创建一个与被检查对象具有相等值的对象)。

class Student:
def __init__(self, name):
self.name = name
def __repr__(self):
return f"{self.__class__.__name__}({self.name!r})"

使用更新后的代码,我们可以在交互式控制台中检查对象,如下所示。如你所见,表示字符串是一个有效的Python表达式,我们可以使用它创建一个Student对象:

>>> student0 = Student("John Smith")
>>> student0
Student('John Smith')

同样,我们可以使用内置的repr()方法来检索表示字符串。因为我们可能希望通过将字符串表示发送给内置的eval()函数来重新构造另一个对象:

>>> student1 = eval(repr(student0))
>>> student1
Student('John Smith')

顺便提一下,我们经常会使用f-string来插入对象的属性,我们使用!r来指定我们想要该字符串的原始表示,因为默认情况下,f-string会调用__str__方法来检索被插入变量的值。在这种情况下,省略!r将使字符串本身被使用,而不是引号内的字符串。下面是一个简单的例子——显然,后一个字符串不能用于创建Student对象:

>>> name = "John Smith"
>>> print(f"Student({name!r})")
Student('John Smith')
>>> print(f"Student({name})")
Student(John Smith)

另一件需要注意的事情是,有时提供一个允许重建对象的有意义的字符串是不实际的。在这种情况下,我们通常使用<>来封装实例的类和一些摘要信息。下面的代码展示了内置类的示例。

>>> from io import BytesIO
>>> BytesIO(b'Medium')
<_io.BytesIO object at 0x11269c9a0>
>>> with open("test.text", 'w') as file:
... print(repr(file))
...
<_io.TextIOWrapper name='test.text' mode='w' encoding='UTF-8'>

str方法

另一个与对象格式化相关的有趣的特殊方法是__str__方法。下面的代码向您展示了如何在自定义类中重写它。

class Student:
def __init__(self, name):
self.name = name
def __str__(self):
return "__str__ is called"

使用修改后的类,让我们看看什么时候调用它。

>>> print(student0)
__str__ is called
>>> str(student0)
'__str__ is called'
>>> f"{student0}"
'__str__ is called'

如上所示,至少有三种情况会导致调用__str__特殊方法。具体来说,print()函数、str()函数(这是预期的,因为它只是一个语法糖)和f-string插值变量都将为对象调用底层的__str__方法。

虽然我们知道使用__str__方法的情况,但问题是实现这个方法的最佳实践是什么。

>>> class Student:
... def __init__(self, name):
... self.name = name
...
... def __str__(self):
... return f"{self.__class__.__name__}, {self.name}"
...
...
... student0 = Student("John Smith")
... print(student0)
...
Student, John Smith

虽然没有通用的方法来定义__str__方法返回的字符串。但是原则是我们应该返回一些关于实例对象的描述性信息。在大多数情况下,我们只返回实例对象的属性来表示对象就可以了。

除了这些点,应该注意的是,如果你的类没有定义__str__方法,Python将查找是否实现了__repr__。如果是,任何调用__str__的函数都会回退到调用__repr__。

format方法

另一个与对象字符串格式化相关的重要特殊方法是__format__方法。下面的代码显示了这个方法在自定义类中的使用方式:

class Student:
def __init__(self, name):
self.name = name
def __format__(self, format_spec):
return "__format__ is called"

正如我们之前所做的,让我们先看看这个方法被调用的常见情况:

>>> student0 = Student("John Smith")
>>> f"{student0}"
'__format__ is called'
>>> format(student0)
'__format__ is called'
>>> print(student0)
<__main__.Student object at 0x114a92c10>
>>> str(student0)
'<__main__.Student object at 0x114a92c10>'

f-string和内置的format()方法都可以调用__format__方法。让我们以f-string为例,向你展示__format__是如何工作的。

你可能注意到,与__repr__和__str__方法不同,__format__方法有一个额外的参数名为format_spec。此参数定义如何将对象格式化为字符串。让我们看看下面代码片段中的一些自定义规范:

>>> class Student:
... def __init__(self, name):
... self.name = name
...
... def __str__(self):
... return f"{self.__class__.__name__}, {self.name}"
...
... def __format__(self, format_spec):
... if format_spec == "i":
... return "".join(x[0] for x in self.name.split())
... elif format_spec == "C":
... return self.name.upper()
... print("___delegate to the built-in format method for generic formatting___")
... return format(str(self), format_spec)
...
...
... student0 = Student("John Smith")
... print("format_spec: i", f"{student0:i}")
... print("format_spec: C", f"{student0:C}")
... print("format_spec: generic", f"{student0:-^30}")
...
format_spec: i JS
format_spec: C JOHN SMITH
___delegate to the built-in format method for generic formatting___
format_spec: generic -----Student, John Smith------

我们定义了两个自定义规范。当说明为i时,它代表首字母,我们返回学生的首字母。另一个规范是C,它代表大写,我们返回学生名的大写形式。除了这两个规范之外,我们还将默认的内置格式委托给适用的字符串格式化。回想一下,当我们使用f-string时,我们在冒号后面指定格式要求。在我们的示例中,当我们将规范指定为i和C时,我们确实得到了所需的格式。

总结

在本文中,我们回顾了Python中有关格式化的三个基本的特殊方法。这里是一个简短的回顾。

__repr__方法是显示一个字符串表示形式,要求返回的是一个有效的Python表达式,可以用来创建类似的对象。当它不适用时,考虑使用“<>”来提供类信息和其他有意义的特性。

__str__方法提供对象的描述性信息。

__format__方法提供了除基本格式之外的自定义格式规范。如果你希望你的对象对于不同的用例有不同的字符串表示,这是很有帮助的。

作者:Yong Cui

deephub翻译组

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
解放军中将在京突然去世,两女儿定居美国,亲弟弟关联25家公司

解放军中将在京突然去世,两女儿定居美国,亲弟弟关联25家公司

求实者
2024-06-12 14:30:22
48岁老头娶小10岁大学生,洞房花烛夜,刚爬上床却被女子踹下床

48岁老头娶小10岁大学生,洞房花烛夜,刚爬上床却被女子踹下床

华人星光
2024-06-15 16:14:48
女主播爆料行业内幕,大量女主播都有价格,周淑怡确实值百万

女主播爆料行业内幕,大量女主播都有价格,周淑怡确实值百万

新游戏大妹子
2024-06-14 11:43:32
随着许家印的没落,其女儿的生活也被曝光,奢侈程度令人咋舌

随着许家印的没落,其女儿的生活也被曝光,奢侈程度令人咋舌

天闻地知
2024-06-14 14:07:23
大陆何时会动手?美国官员表态,台湾名嘴:赖清德赌大陆不会攻台

大陆何时会动手?美国官员表态,台湾名嘴:赖清德赌大陆不会攻台

千里持剑
2024-06-15 13:25:04
2023年国家自然科学基金评审专家名单汇总

2023年国家自然科学基金评审专家名单汇总

高分子科学前沿
2024-06-16 07:53:29
中国女排3-2土耳其!赛后评分:张常宁满分+4将出彩,一将需提升

中国女排3-2土耳其!赛后评分:张常宁满分+4将出彩,一将需提升

理工男评篮球
2024-06-15 23:27:43
“坐滩”舰终迎大结局?封锁见效,菲驻军或撤离,中方:允许离开

“坐滩”舰终迎大结局?封锁见效,菲驻军或撤离,中方:允许离开

国学聚焦
2024-06-15 14:41:15
3-0!6000万水货,打脸曼联名宿:西班牙走不远?一眼被看穿?

3-0!6000万水货,打脸曼联名宿:西班牙走不远?一眼被看穿?

贝塔说体育
2024-06-16 05:48:29
开始了!俄罗斯军人亲属呼吁官员儿子顶替亲人

开始了!俄罗斯军人亲属呼吁官员儿子顶替亲人

亡海中的彼岸花
2024-06-15 08:56:51
邢天虎-陕西延长石油(集团)有限责任公司原副董事长

邢天虎-陕西延长石油(集团)有限责任公司原副董事长

开心体育站
2024-06-16 11:19:12
新闻背后:贵州卫健委美女厅官杨慧落马,人上人到鬼中鬼的人生路

新闻背后:贵州卫健委美女厅官杨慧落马,人上人到鬼中鬼的人生路

肖飞说
2024-06-16 01:24:07
22岁小伙雇45岁保姆后,整天不出门在家过二人世界

22岁小伙雇45岁保姆后,整天不出门在家过二人世界

牛城王小帅
2024-06-12 13:48:47
50年石油美元协议到期 沙特:不再续约

50年石油美元协议到期 沙特:不再续约

南方都市报
2024-06-16 07:03:39
广州城中村简直是炼狱

广州城中村简直是炼狱

悠闲葡萄
2024-06-16 14:12:31
某音网红“璇子baby”被认出疑是探花203期中女主?

某音网红“璇子baby”被认出疑是探花203期中女主?

挪威森林
2024-06-16 07:25:21
无人驾驶小车成道路杀手!在后沙峪的交通噩梦

无人驾驶小车成道路杀手!在后沙峪的交通噩梦

悠闲葡萄
2024-06-15 12:43:58
上海这夜,耍大牌周也和勒肉张碧晨,都败给了“全裹”出镜的高叶

上海这夜,耍大牌周也和勒肉张碧晨,都败给了“全裹”出镜的高叶

一娱三分地
2024-06-16 08:55:03
再见曼城!1.2亿标王挂牌出售!顶撞瓜帅,不道歉,或转投大巴黎

再见曼城!1.2亿标王挂牌出售!顶撞瓜帅,不道歉,或转投大巴黎

阿泰希特
2024-06-16 11:34:34
直击:白金汉宫礼台上威廉凯特恩爱对视,夏洛特站C位女王范十足

直击:白金汉宫礼台上威廉凯特恩爱对视,夏洛特站C位女王范十足

文雅笔墨
2024-06-16 01:01:18
2024-06-16 16:10:44
deephub
deephub
CV NLP和数据挖掘知识
1369文章数 1416关注度
往期回顾 全部

科技要闻

iPhone 16会杀死大模型APP吗?

头条要闻

"地铁上被诬陷偷拍"男子将直播带货:需面对现实问题

头条要闻

"地铁上被诬陷偷拍"男子将直播带货:需面对现实问题

体育要闻

没人永远年轻 但青春如此无敌还是离谱了些

娱乐要闻

上影节红毯:倪妮好松弛,娜扎吸睛

财经要闻

打断妻子多根肋骨 上市公司创始人被公诉

汽车要闻

售17.68万-21.68万元 极狐阿尔法S5正式上市

态度原创

旅游
家居
本地
房产
公开课

旅游要闻

@毕业生,江苏这些景区可享免票或优惠

家居要闻

空谷来音 朴素留白的侘寂之美

本地新闻

粽情一夏|海河龙舟赛,竟然成了外国人的大party!

房产要闻

万华对面!海口今年首宗超百亩宅地,重磅挂出!

公开课

近视只是视力差?小心并发症

无障碍浏览 进入关怀版