Python小白学习教程从入门到入坑------第二十二课 面向对象基础【下】{构造函数析构函数}(语法进阶)

一、构造函数__init__()

1.1 构造函数基础

在Python中,__init__() 方法是一个特殊的方法,被称为类的构造函数(constructor)。它主要用于在创建类的新实例(对象)时初始化该对象的属性。每当通过类创建对象时,Python会自动调用这个方法

作用:通常用来做属性初始化或者赋值操作

注意:在类实例化对象的时候,会被自动调用

eg:

# 注意:在类实例化对象的时候,会被自动调用
class Test:def __init__(self):      # self---一个实例方法print("这是__init__()函数")
# 实例化对象:对象名 = 类名()
te = Test()
# 输出结果:这是__init__()函数

以下是一些关于 __init__() 方法的要点:

命名:方法名必须是 __init__,并且前后各有两个下划线

参数:第一个参数通常是 self,它代表类的实例本身。在调用方法时,不需要显式传递 self 参数,Python会自动处理,其他参数用于初始化对象的属性

初始化属性:在 __init__ 方法内部,可以使用 self 来访问和设置对象的属性

没有返回值:构造函数不应该有返回值(实际上,如果尝试返回非 None 的值,会导致 TypeError)

1.2 构造函数举例

那么为什么我们要选择使用构造函数呢,举一个小小的例子说明一下:

class Person:     # 人类def __init__(self):self.name = "junjun"      # 实例属性   姓名self.age = 18             # 年龄self.height = 163          # 身高def play(self):print(f'{self.name}在打王者荣耀')def introduce(self):print(f"{self.name}的年龄是{self.age},身高是{self.height}cm")
# 实例化对象
pe = Person()
pe.play()
pe.introduce()
# 实例化第二个对象
pe2 = Person()
pe2.play()
pe2.introduce()
# 输出结果:
# junjun在打王者荣耀
# junjun的年龄是18,身高是163cm
# junjun在打王者荣耀
# junjun的年龄是18,身高是163cm

在这个例子中,如果想要更改输出结果必须要在实例属性位置一 一修改,很麻烦,这时就需要用到我们的构造函数了

class Person:  def __init__(self, name, age):  self.name = name  # 初始化属性 name  self.age = age    # 初始化属性 age  # 创建 Person 类的实例  
person1 = Person("Alice", 30)  
person2 = Person("Bob", 25)  # 访问对象的属性  
print(person1.name)  # 输出: Alice  
print(person1.age)   # 输出: 30  
print(person2.name)  # 输出: Bob  
print(person2.age)   # 输出: 25

在这个例子中,Person 类有一个构造函数 __init__(),它接受三个参数:self、name 和 age

在创建 Person 类的实例时,传递的 name 和 age 参数被用来初始化对象的 name 和 age 属性

你也可以在 __init__() 方法中执行其他初始化操作,比如设置默认值、进行输入验证等

eg:带有默认值的构造函数

class Person:  def __init__(self, name, age=None):  self.name = name  self.age = age if age is not None else 0  # 如果未提供 age,则默认设置为 0  # 创建 Person 类的实例  
person1 = Person("Alice")  
person2 = Person("Bob", 25)  # 访问对象的属性  
print(person1.name)  # 输出: Alice  
print(person1.age)   # 输出: 0  
print(person2.name)  # 输出: Bob  
print(person2.age)   # 输出: 25

 在这个例子中,age 参数有一个默认值 None,如果创建对象时没有提供 age 参数,则将其设置为 0

二、析构函数 __del__()

删除对象的时候,解释器会默认调用__del__() 方法

2.1 析构函数基础

在 Python 中,析构函数(也称为析构器)是一个特殊的方法,用于在对象被销毁或垃圾回收之前执行清理操作

析构函数的名称是 __del__()(注意双下划线)

当 Python 的垃圾回收机制确定对象不再被引用时,它会调用这个方法来释放对象所占用的资源,比如关闭文件、释放网络连接等

2.2  __del__() 方法的一些关键点

调用时机:__del__() 方法是在对象生命周期结束时调用的,这通常发生在对象不再被任何变量引用时。然而,确切的调用时机是由垃圾回收机制决定的,因此它是不可预测的

手动删除:即使对象仍被引用,如果显式地调用 del 语句来删除对象的引用,Python 也不会立即调用 __del__() 方法,而是等到对象实际上被垃圾回收时才调用

异常处理:如果在 __del__() 方法中抛出了异常,这个异常通常会被忽略,并且不会传播到调用者。这意味着在析构函数中处理异常时需要格外小心

循环引用:在涉及循环引用的复杂对象中,垃圾回收可能会变得复杂。在这种情况下,__del__() 方法可能永远不会被调用

资源管理:虽然 __del__() 方法可以用于资源管理,但更好的做法是使用上下文管理器(通过实现 __enter__() 和 __exit__() 方法)和 with 语句。这种方式可以确保资源在块结束时被正确释放,即使发生异常也是如此

继承:如果子类没有定义自己的 __del__() 方法,它会继承父类的 __del__() 方法。如果子类定义了 __del__() 方法,并且还想调用父类的 __del__() 方法,那么需要显式地调用 super().__del__()

2.3 __del__() 举例

1、正常运行时,不会调用__del__(),对象执行结束之后,系统会自动调用__del__()

eg:

class Person:def __init__(self):print("我是__init__()")def __del__(self):print("被销毁了")
p = Person()
print("这是倒数第二行代码")
print("这是最后一行代码")
# 输出结果:
# 我是__init__()
# 这是倒数第二行代码
# 这是最后一行代码
# 被销毁了

2、删除对象的时候,解释器会默认调用_del()方法

在 Python 中,当对象不再被任何变量引用,并且垃圾回收器决定回收该对象的内存时,解释器会调用该对象的 __del__() 方法(如果定义了的话)

然而,需要注意的是,__del__() 方法的调用并不是由 del 语句直接触发的,而是由垃圾回收机制在对象生命周期结束时进行的。

del 语句的作用是删除对对象的引用,使对象成为垃圾回收的目标。但是,实际的内存回收和 __del__() 方法的调用是由 Python 的垃圾回收器在后台管理的,并且这个过程是异步的,不可预测的。

eg:

class MyClass:  def __init__(self, name):  self.name = name  print(f"Object {self.name} created.")  def __del__(self):  print(f"Object {self.name} destroyed (__del__ called).")  # 创建一个对象并赋值给变量 obj  
obj = MyClass("ExampleObject")  # 此时,obj 引用了一个 MyClass 对象  # 使用 del 语句删除对对象的引用  
del obj  # 此时,MyClass 对象不再被 obj 引用  
# 但是,__del__() 方法可能还没有被调用  
# 因为垃圾回收器还没有决定回收这个对象的内存  # 为了演示目的,我们可以强制进行垃圾回收(通常不推荐这样做)  
import gc  
gc.collect()  # 尝试立即回收垃圾  # 如果垃圾回收器决定回收该对象的内存,  
# 它会在此时调用对象的 __del__() 方法  
# 输出应该是:Object ExampleObject destroyed (__del__ called).  
# 但是,请注意,由于垃圾回收的具体实现和时机,  
# 这个输出可能不会在 del 语句之后立即出现。

在这个例子中,del obj 语句删除了对 MyClass 对象的引用,但是 __del__() 方法的调用取决于垃圾回收器的行为

我们通过调用 gc.collect() 来尝试强制垃圾回收,以便观察 __del__() 方法的调用

然而,即使这样,__del__() 方法的调用也不是确定的,因为垃圾回收器可能会决定稍后再回收内存

重要的是要理解,__del__() 方法通常不是进行资源管理的最佳方式

更好的做法是使用上下文管理器(通过实现 __enter__() 和 __exit__() 方法)和 with 语句,这样可以确保资源在块结束时被正确释放,即使发生异常也是如此

__del__() 方法应该仅用于需要在对象销毁时执行特定清理操作的极少数情况

今天的分享就到这里了,糊涂君-Q希望能够帮助到大家,大家有什么疑问欢迎在评论区互相交流,文中有什么错误同样也欢迎大家批评指正,期待和大家共同进步~

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

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

相关文章

Hive的数据存储格式

目录 一、前言 二、存储格式 2.1、文本格式(TextFile) 2.1.1、定义与特点 2.1.2、存储与压缩 2. 1.3、使用场景 2.2、行列式文件(ORCFile) 2.2.1、ORC的结构 2.2.2、ORC的数据类型 2.2.3、ORC的压缩格式 2.2.3、ORC存储…

【云原生】云原生后端:网络架构详解

目录 引言一、微服务间的通信1.1 通信方式概览1.2 HTTP/REST1.3 gRPC1.4 消息队列1.5 GraphQL 二、API网关2.1 API网关架构示例2.2 API网关实现示例 三、服务发现3.1 服务发现实现示例3.2 服务发现的优势 四、网络安全4.1 网络安全最佳实践4.2 网络安全架构示例 总结参考资料 引…

蓝牙BLE开发——红米手机无法搜索蓝牙设备?

解决 红米手机,无法搜索附近蓝牙设备 具体型号当时忘记查看了,如果你遇到有以下选项,记得打开~ 设置权限

华为自研仓颉编程语言官网上线 首个公测版本开放下载

仓颉编程语言官网正式公开上线,同时首个公测版本开放下载。本次仓颉编程语言官网上线了首页、在线体验、文档、学习、下载、动态以及三方库共六个模块,可供开发和学习和体验。 据悉,仓颉编程语言是在今年6月的华为开发者大会上正式公布&…

【AI换脸整合包及教程】AI换脸技术新贵:Rope换脸工具全面解析

随着人工智能技术的快速发展,AI换脸技术逐渐走入大众视野,成为一种既有趣又实用的技术。从早期的DeepFace到后来的Faceswap,再到如今的Rope,每一次技术的革新都带来了更高效、更自然的换脸体验。Rope作为当前市场上最炙手可热的AI…

Ubuntu Linux

起源与背景 Ubuntu起源于南非,其名称“Ubuntu”来源于非洲南部祖鲁语或豪萨语,意为“人性”、“我的存在是因为大家的存在”,这体现了非洲传统的一种价值观。Ubuntu由南非计算机科学家马克沙特尔沃斯(Mark Shuttleworth&#xff…

angular实现dialog弹窗

说明&#xff1a; angular实现dialog弹窗 效果图&#xff1a; step1&#xff1a;E:\projectgood\ajnine\untitled4\src\app\apple\apple.component.html <button mat-button (click)"openDialog()">Open dialog</button>step2&#xff1a;E:\projectgo…

《JVM第4课》程序计数器

无痛快速学习入门JVM&#xff0c;欢迎订阅本免费专栏 Java程序计数器&#xff08;Program Counter Register&#xff09;是Java虚拟机&#xff08;JVM&#xff09;运行数据区的一个组成部分。每个线程都有它自己的程序计数器&#xff0c;这部分内存用于存储该线程下一条要执行的…

闪存学习_1:Flash-Aware Computing from Jihong Kim

闪存学习_1&#xff1a;Flash-Aware Computing from Jihong Kim 前言一、Storage Media&#xff1a;NAND Flash Memory1、概念2、编程和擦除操作3、读操作4、异地更新操作&#xff08;Out-Place Update&#xff09;5、数据可靠性6、闪存控制器&#xff08;SSD主控&#xff09;7…

嵌入式web开发:boa、lighttpd

嵌入式web开发&#xff1a;boa、lighttpd https://blog.csdn.net/m0_37105371/category_10937068.html BOA服务器的移植-CSDN博客 【第1部分&#xff1a;boa服务器部署到ubuntu里】 http://www.boa.org/boa-0.94.13.tar.gz tar xvzf boa-0.94.13.tar.gz cd boa-0.94.13/src/ a…

使用模板工厂模式实现动态创建C++对象

一、前言 在现代C开发中&#xff0c;工厂模式是常见的设计模式之一&#xff0c;能够有效地解耦对象创建与使用代码。本文介绍一个模板类 ComponentsFactory&#xff0c;它运用了模板编程和工厂模式&#xff0c;实现了一种动态的对象创建方式。通过该工厂&#xff0c;我们可以基…

Linux_04 Linux常用命令——tar

一、命令格式 tar [选项] [归档文件] [要处理的文件或目录]1、选项 c创建归档文件x解压缩归档文件z使用gzipj使用bzip2v处理过程显示信息f指定归档文件名称 2、归档文件-可指定目录及文件名 /home/wang.tar.gz 3、要处理的文件或目录 /home/study1/wang 二、常见命令 t…

【1个月速成Java】基于Android平台开发个人记账app学习日记——第一天

24.10.31 开发前准备 IDE下载与配置GitHub仓库创建 IDE下载与配置 下载最新版本IDEA&#xff0c;卸载之前的旧版本 后面一路跟着安装的默认选项走即可 安装完以后这个最新的可以把我再jetbrains的其他软件设置导入&#xff0c;很方便 接下来创建新的项目并进行安卓应用开发…

【elkb】索引生命周期管理

索引生命周期管理 Index lifecycle management(索引生命周期管理)是elasticsearch提供的一种用于自动管理索引的生命周期的功能。允许使用者定义索引的各个阶段&#xff0c;从创建至删除。并允许使用者在每个阶段定义索引需要执行的特定动作。这些动作包含索引创建&#xff0c…

HttpServer模块 --- 封装TcpServer支持Http协议

目录 模块设计思想 模块代码实现 模块设计思想 本模块就是设计一个HttpServer模块&#xff0c;提供便携的搭建http协议的服务器的方法。 那么这个模块需要如何设计呢&#xff1f; 这还需要从Http请求说起。 首先http请求是分为静态资源请求和功能性请求的。 静态资源请求…

外接数据库给streamlit等web APP带来的变化

之前我采用sreamlit制作了一个调查问卷的APP&#xff0c; 又使用MongoDB作为外部数据存储&#xff0c;隐约觉得外部数据库对于web APP具有多方面的意义&#xff0c;代表了web APP发展的趋势之一&#xff0c;似乎是作为对这种趋势的响应&#xff0c;streamlit官方近期开发了st.c…

sql题库中常见问答

一.解答题 (15*2) 1 Drop, delete,truncates 三者的区别? ①、drop和truncate属于数据库的定义语言(DDL) ②、delete属于数据库的操作语言(DML) ③、drop可以删除全表结果,且删除的同时会删除表数据 ④、delete 和truncate只能删除表数据,truncate会删除表数据一起…

黄山谷捷IPO拟募资5亿元,增强核心竞争力

根据深交所发行上市审核进度&#xff0c;10月28日&#xff0c;黄山谷捷股份有限公司首发申请审核状态变更为“提交注册”。据悉&#xff0c;黄山谷捷本次拟公开发行不超过2,000万股&#xff0c;占本次发行后总股本的比例不低于25.00%。 招股书&#xff08;注册稿&#xff09;披…

无人机拦截捕获/直接摧毁算法详解!

一、无人机拦截捕获算法 网捕技术 原理&#xff1a;抛撒特殊设计的网具&#xff0c;捕获并固定无人机。 特点&#xff1a; 适用于小型无人机。 对无人机的损害较小&#xff0c;基本不影响其后续使用。 捕获成功率较高&#xff0c;且成本相对较低。 应用实例&#xff1a;…

.NET Core WebApi第4讲:控制器、路由

一、控制器是什么&#xff1f; 1、创建一个空的API控制器&#xff1a;TestController.cs 2、里面有一个类叫TestController&#xff0c;把它叫做控制器 因为它继承了ControllerBase类&#xff0c;ControllerBase类里提供了一系列的方法&#xff0c;使得TestController这个类具…