81、Python之鸭子类型:从魔法函数看对象的字符串呈现

引言

前面已经介绍了鸭子类型的概念,以及Python中支撑鸭子类型理念的“魔法函数”的体系。Python中的魔法函数分为几大类,本文我们首先从最简单的自定义类型的字符串呈现来切入,逐步理解并掌握Python中的魔法函数的完整架构。

本文的主要内容有:

1、print()函数的内部运行机制

2、对象的字符串表示的默认实现

3、通过魔法函数自定义对象字符串表示的实现

print()函数的内部运行机制

关于print()函数的使用,我们前面已经进行详细的介绍,结合print()函数的定义文档,再来简单回顾一下:

23ec9cc292719961fa01acc09e373dfc.jpeg

通常情况下,我们只需要将要输出的对象作为位置参数传递给print()函数,即可完成一个对象的打印输出。其实,结合sep、end、file参数,我们可以实现更多的打印效果:

1、sep参数,默认情况下为一个空格,当我们需要输出多个对象,并自定义分隔符时,可以指定该参数。

2、end参数,默认情况下为一个回车,也可以自行指定。

3、file参数,默认情况下其实就是sys.stdout,也可以指定自己的文件流,就变成了往文件中写入数据了,比如日志等。

以上,大概就是我们之前介绍过的关于print()函数的使用了。

但是,为什么有的对象的输出字符串包含了元素、属性等,有些对象的输出就是比较奇怪的一串字符串?要回答这个问题,就要涉及到print()函数的作用机制了,我们直接说结论:

当我们调用print(obj)函数时,Python内部的处理机制是这样的:

1、检查对象是否实现了__str__()方法,如果实现了,则调用__str__()方法,然后输出其返回值。

2、如果对象没有实现__str__()方法,则会检查对象是否实现了__repr__()方法,如果实现了,则调用__repr__()方法,然后输出其返回值。

3、如果对象两个方法都没有实现,则会使用对象的默认字符串表示形式。

需要说明的,Python内置的str类,也是这样类似的实现逻辑,可以从定义中看出:

37d13d1448108fbf2d95e2118435f79d.jpeg

对象的字符串表示的默认实现

对象的字符串表示的默认实现,其实,只要写过Python代码,应该多少都接触过,我们以实际代码为例,来简单看一下:

class DaGongRen:def __init__(self, name, age):self.name = nameself.age = ageif __name__ == '__main__':zs = DaGongRen('张三', 18)print(zs)print(str(zs))

执行结果:

a0402d47e139300491da98c5d3b1f0f3.jpeg

这一串看着有些奇怪的字符串,其实是一个固定的表示格式。其中隐含了模块名、类名,以及,大概是这样一个逻辑,我们通过代码直接演示一下:

class DaGongRen:def __init__(self, name, age):self.name = nameself.age = agedef my_str(self):return f"<{self.__class__.__module__}.{self.__class__.__name__} object at {hex(id(self))}>"if __name__ == '__main__':zs = DaGongRen('张三', 18)print(zs)print(str(zs))print(zs.my_str())

执行结果:

5b0a1a22c8542f0b78b1c9ce82bb9cbb.jpeg

从执行结果可以看出,我们自定义的my_str()方法的输出内容,与对象的默认字符串表示的输出,是完全一样的。

其实,之所以会有这个默认实现,是由于Python中的新式类,默认都是继承自object这个基类。这种默认的字符串表示是通过object类的__repr__()方法实现的。

通过魔法函数自定义对象字符串表示的实现

从print()函数的内部作用机制,我们已然可以知道,通过魔法函数__str__()和__repr__(),可以实现自定义对象字符串表示的行为。这也是内部类型,比如容器等,等够在print()输出时,呈现出更加人性化的内容,更加便于开发者的使用、调试。

还是先通过代码来看一下吧:

class DaGongRen:def __init__(self, name, age):self.name = nameself.age = agedef my_str(self):return f"<{self.__class__.__module__}.{self.__class__.__name__} object at {hex(id(self))}>"def __str__(self):return f"{self.__class__.__name__}(name = {self.name}, age = {self.age})"if __name__ == '__main__':zs = DaGongRen('张三', 18)print(zs)print(str(zs))print(zs.my_str())

执行结果:

05b347ae986e5e352a4eefb1bcec25de.jpeg

从执行结果可以看出,print(obje)和str(obj),都已经自动调用了我们自定义的__str__()方法。

当然,这里我们换成__repr__()方法,也是可以的。

需要说明的是,大多数情况下,使用__str__()方法或者__repr__()方法的效果都是一样的,但是,二者还是有所区别的,主要在使用场景上:

1、__str__()方法,用于生成面向用户的可读性字符串表示,通常会被用于print()函数或者str()函数(可以理解为是调用方,虽然__repr__也是可以的,只能当做一种约定、习俗)。

2、__repr__()方法,更多地用于生成开发者的详细字符串表示,通常用于调试时使用。比如通过repr()函数调用或者直接在交互式解释器中输入对象等。

感兴趣的同学,可以自行定义__str__()和__repr__()的不同实现,然后对比print()、str()、repr()的输出内容,来看两个方法各自的触发机制。

总结

本文基于对鸭子类型和魔法函数概念的理解的基础上,首先回顾了print()函数的简单使用,介绍了print()等类似的字符串呈现的函数的作用机制,然后介绍了通过__str__()、__repr__()实现自定义类型的对象的字符串表示的自定义实现。

感谢您的拨冗阅读,希望对您有所帮助!

363ae322bed4d4f6e90962ddf54c8777.jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/432779.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

玩转指针(3)

一、字符指针变量 字符指针变量&#xff08;如char* p&#xff09;的两种赋值方式 ①将字符类型地址赋值给字符指针变量 int main() {char a w;char* p &a;*p m;return 0; }②将常量字符串赋值给字符指针变量 常量字符串的介绍&#xff1a;用" "引起来的就…

以Flask为基础的虾皮Shopee“曲线滑块验证码”识别系统部署

以Flask为基础的虾皮Shopee“曲线滑块验证码”识别系统部署 一、验证码类型二、简介三、Flask应用 一、验证码类型 验证码类型&#xff1a;此类验证码存在两个难点&#xff0c;一是有右侧有两个凹槽&#xff0c;二是滑块的运动轨迹不是直线的&#xff0c;而是沿着曲线走的&…

STM32通过HAL库编码方式,在烧写一次程序后,单片机在仿真器上识别不到

在将项目从裸机移植到rtt过程中&#xff0c;总体调试跑不通ADC&#xff0c;进行了单独调试&#xff0c;新程序烧写进单片机后&#xff0c;仿真器再也识别不到单片机。一遍遍检查后发现HAL库没有配置完全。 SYS需要设置成 Serial Wire&#xff0c;忘记设置就成了No Debug,写这么…

基于nodejs+vue的水产品销售管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

如何在 macOS(MacBook Pro、Air 和 iMac)上恢复未保存的 Word 文档

Microsoft Word 在许多用户中很受欢迎&#xff0c;并且有多种用途。无论是为学校写论文、在办公室写报告还是其他许多事情。但是不保存文档并丢失数据可能是您可能面临的最可怕的噩梦。但是&#xff0c;也有几种方法可以在 macOS 上恢复未保存的 Word 文档。 用户在 Windows P…

wpf中如何访问控件和生成使用事件?

实际上对于初次使用wpf的同学来说&#xff0c;尤其是有winform编程经验的童鞋来说&#xff0c;最需要解决的就是快速掌握访问控件的方法以及生成和使用事件。这样才能让页面具有最起码的交互性。下面我们来分别讲述。 文章原出处&#xff1a;https://blog.csdn.net/haigear/ar…

网络原理(4)——网络层(IP)、数据链路层

1. IP 协议 基本概念&#xff1a; 主机&#xff1a;配有 IP 地址&#xff0c;但是不进行路由控制的设备 路由器&#xff1a;即配有 IP 地址&#xff0c;又能进行路由控制 节点&#xff1a;主机和路由器的统称 IP 协议报头格式 1) 4 位版本&#xff1a;实际上只有两个取值&…

C语言题目之单身狗2

文章目录 一、题目二、思路三、代码实现 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、题目 二、思路 第一步 在c语言题目之打印单身狗我们已经讲解了在一组数据中出现一个单身狗的情况&#xff0c;而本道题是出现两个单身狗的情况。根据一个数…

9.C++程序中的选择语句

选择语句一共分为两种&#xff1a;条件语句和开关语句 其中条件语句叫if语句&#xff0c;常见的形式为&#xff1a;if ... else ... ; 再复杂一些为if... else if ... else ... ; 开关语句又叫switch语句&#xff0c;类型于开关的使用形式常见的有 switch (var) case : ... b…

tauri中加载本地文件图片或者下载网络文件图片后存储到本地,然后通过前端页面展示

有一个需求是需要将本地上传的文件或者网络下载的文件存储到本地&#xff0c;并展示在前端页面上的。其实如果只是加载本地文件&#xff0c;然后展示还是挺简单的&#xff0c;可以看我的文章&#xff1a;tauri程序加载本地图片或者文件在前端页面展示-CSDN博客 要想实现上述需…

JS 历史简介

目录 1. JS 历史简介 2. JS 技术特征 1. JS 历史简介 举例&#xff1a;在提交用户的注册信息的时候&#xff0c;为避免注册出现错误后重新填写信息&#xff0c;可以在写完一栏信息后进行校验&#xff0c;并提示是否出现错误&#xff0c;这样会大大提高用户提交的成功率&…

gradle镜像配置

当我们在Android Studio中新建项目或者打开已有项目时&#xff0c;会下载gradle文件&#xff0c;当使用官方的下载源时很慢&#xff0c;经常会下载失败&#xff0c;国内我们可以使用腾讯或者阿里的镜像&#xff0c;一般下载速度很快。 一、gradle下载地址 官网地址&#xff1…

C语言指针系列2——加深理解

大家&#xff0c;今天讲的知识点是一块儿一块儿的&#xff0c;所以大家要好好学习喔~ 话不多说&#xff0c;开始正题 关键字&#xff1a;const &#xff08;三种用法&#xff09; 1. int* const p; 2. int const* p; 3. const int* const p; 首先我们要了解一下const&#xff…

【计算机组成原理】实验一:运算器输入锁存器数据写实验

目录 实验要求 实验目的 主要集成电路芯片及其逻辑功能 实验原理 实验内容及步骤 实验内容 思考题 实验要求 利用CP226实验箱上的K16&#xff5e;K23二进制拨动开关作为DBUS数据输入端&#xff0c;其它开关作为控制信号的输入端&#xff0c;将通过K16&#xff5e;K23设定…

【学习笔记】SSL/TLS证书安全机制之证书透明

1、概念 CT - Certificate Transparency&#xff0c;证书透明 2、Trying to Solve 如果意外的 CA 为我们的域名颁发证书&#xff0c;我们是不可见&#xff0c;这就是证书透明&#xff08;CT&#xff09;要解决的问题 3、How CT Works 任何CA机构颁发的所有证书的公共登记处&…

西门子1200PLC模拟量指令读出来的值好像不太对劲的样子

问题&#xff1a;模拟量指令读出来的值好像不太对劲的样子 各位高手看看&#xff0c;是不是哪里错了&#xff0c;传感器4-20ma的规格&#xff0c;我取值0-27648&#xff0c;我要换算成N,后面范围是0-200&#xff0c;但是值为什么都是小数点啊&#xff0c;而且和实际的压力怎么看…

使用宝塔部署项目在win上

项目部署 注意&#xff1a; 前后端部署项目&#xff0c;需要两个域名&#xff08;二级域名&#xff0c;就是主域名结尾的域名&#xff0c;需要在主域名下添加就可以了&#xff09;&#xff0c;前端一个&#xff0c;后端一个 思路&#xff1a;访问域名就会浏览器会加载前端的代…

VMware虚拟机Centos操作系统——配置docker,运行本地打包的镜像,进入conda环境(vmware,docker新手小白)

1.docker-centos运行sudo yum install -y yum-utils报错 遇到问题 解决&#xff1a; 进入/etc/yum.repos.d目录下找到 CentOS-Base.repo&#xff0c;执行下面两个命令&#xff1a; cp CentOS-Base.repo CentOS-Base.repo.backupvi CentOS-Base.repo 进入后改成&#x…

恶意Bot流量识别分析实践

1、摘要 随着互联网的发展&#xff0c;自动化工具和脚本&#xff08;Bots&#xff09;的使用越来越普遍。虽然一些善意 Bots 对于网站的正常运行和数据采集至关重要&#xff0c;但恶意 Bots 可能会对网站带来负面影响&#xff0c;如爬取敏感信息、恶意注册、刷流量等。因此&am…

11. Map和Set

一、二叉搜索树 1. 概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树&#xff1a; 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根…