类的特殊成员
1|0__doc__
表示类的描述信息


2|0__module__ 和 __class__
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
以下文字描述过于麻烦,直接上图比较简单明了。注意截图时运行的是哪个模块。
3|0__init__()方法:通过类创建对象时,自动触发执行。
4|0__call__()
表示当前操作的对象的类是什么
使用类装饰器还可以依靠类内部的__call__方法,当使用 @ 形式将装饰器附加到函数上时,就会调用此方法。
5|0__int__()
当执行 int(对象) 时,自动调用 __int__() 方法
6|0__str__()和__repr__
__str__和__repr__返回值都必须是字符串类型
如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
但大部分情况下都不是这么使用的。以下打印时,得到一个地址和类名,但是根本不知道这个类的有用信息。
这时候,需要在内部有个__str__方法。
其实,当你调用 print(a) 时,自动变成 print(str(a)) ,然后自动去寻找 a 中的 __str__。
如果没有,则调用object里面的__str__
那么当我们赋值变量成list类型,然后print该变量的时候,打印的也是一个list对象,为什么不显示一个内存地址呢?因为list类里面重定制了__str__
当我们print(“%s”)后面带一个对象的时候,我们调用的就是对象的str方法。
%s str() 直接打印,实际上都是走的__str_
%r repr() 实际上都是走的__repr__
__ repr__是__str__的备胎。当缺失__str__时,会调用__repr__。但是缺失__repr__的时候,不缺调用__str__。
print(obj)/‘%s’%obj/str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串。
如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__
repr(),只会找__repr__,如果没有找父类的。
7|0__add__()
当你想要让两个 类对象 相加的时候使用。如果没有 __add__() 方法,会报错。
要注意,__add__() 方法有两个参数。self 表示对象自己,other 表示要相加的第二个对象。
8|0__del__()
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的 |
如果没有手动删,python自己也会删除。如下:
内部有个引用计数,就是一个计数器,只有当解释器通过引用计数发现不再使用这个变量的时候,才会进行自动删除。
第二,当变量超过一定的数量(700),才会进行自动删除。
9|0__dict__
查看类或对象中的所有成员
10|0__getitem__、__setitem__、__delitem__
用于索引操作,如字典。以上分别表示获取、设置、删除数据
字典就是这样实现的
11|0 __getslice__、__setslice__、__delslice__
该三个方法用于分片操作,如:列表
12|0__iter__
用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 __iter__



以上步骤可以看出,for循环迭代的其实是 iter([11,22,33,44]) ,所以执行流程可以变更为:
13|0__bases__
在python里要查看一个类型的父类,使用它的__bases__属性可以查看。
14|0__eq__
15|0__hash__
16|0__new__
构造方法:创建一个对象
在__init__的时候已经有一个对象了,这个对象就是__new__构造出来的。
1、为什么__new__传入的是cls而不是self?因为这时候还没有对象,所以需要传入的是类。
2、__new__ 的return给谁了?给__init__的self。
设计模式:23种
单例模式:一个类,始终 只有一个 实例
当你第一次实例化这个类的时候,就创建一个实例化的对象。当你之后再来实例化的时候,就用之前创建的那个对象。
16|1一、__init__ 方法是什么?
__init__ 方法通常用在初始化一个类实例的时候。例如:
这样便是__init__最普通的用法了。但__init__其实不是实例化一个类的时候第一个被调用 的方法。当使用 Persion(name, age) 这样的表达式来实例化一个类时,最先被调用的方法 其实是 __new__ 方法。
16|2二、__new__ 方法是什么?
先看下object类中对__new__()方法的定义:
object将__new__()方法定义为静态方法,并且至少需要传递一个参数cls,cls表示需要实例化的类,此参数在实例化时由Python解释器自动提供。
__new__方法接受的参数虽然也是和__init__一样,但__init__是在类实例创建之后调用,而 __new__方法正是创建这个类实例的方法。
执行结果:
通过运行这段代码,我们可以看到,__new__方法的调用是发生在__init__之前的。其实当 你实例化一个类的时候,具体的执行逻辑是这样的:
1.p = Person(name, age)
2.首先执行使用name和age参数来执行Person类的__new__方法,这个__new__方法会 返回Person类的一个实例(通常情况下是使用 super(Persion, cls).__new__(cls, … …) 这样的方式),__new__()必须要有返回值,返回实例化出来的实例。需要注意的是,可以return父类__new__()出来的实例,也可以直接将object的__new__()出来的实例返回。
3.然后利用这个实例来调用类的__init__方法,__init__()有一个参数self,该self参数就是__new__()返回的实例,__init__()在__new__()的基础上可以完成一些其它初始化的动作,__init__()不需要返回值。若__new__()没有正确返回当前类cls的实例,那__init__()将不会被调用,即使是父类的实例也不行。
我们可以将类比作制造商,__new__()方法就是前期的原材料购买环节,__init__()方法就是在有原材料的基础上,加工,初始化商品环节。
所以,__init__ 和 __new__ 最主要的区别在于:
1.__init__ 通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性, 做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法。
2.__new__ 通常用于控制生成一个新实例的过程。它是类级别的方法。
但是说了这么多,__new__最通常的用法是什么呢,我们什么时候需要__new__?
16|3三、__new__ 的作用
依照Python官方文档的说法,__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass。
假如我们需要一个永远都是正数的整数类型,通过集成int,我们可能会写出这样的代码。
通过重载__new__方法,我们实现了需要的功能。
另外一个作用,关于自定义metaclass。其实我最早接触__new__的时候,就是因为需要自定义 metaclass,但鉴于篇幅原因,我们下次再来讲python中的metaclass和__new__的关系。
16|4四、用__new__来实现单例
事实上,当我们理解了__new__方法后,我们还可以利用它来做一些其他有趣的事情,比如实现 设计模式中的 单例模式(singleton) 。
因为类每一次实例化后产生的过程都是通过__new__来控制的,所以通过重载__new__方法,我们 可以很简单的实现单例模式。
输出结果:
17|0__metaclass__
上述代码中,obj 是通过 Foo 类实例化的对象,其实,不仅 obj 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象。
如果按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。
所以,obj对象是Foo类的一个实例,Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。
那么,创建类就可以有两种方式:
a). 普通方式
b).特殊方式(type类的构造函数)
==》 类 是由 type 类实例化产生
那么问题来了,类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?
答:类中有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程。

其它:
参考:
1. 详解 python 中的 __new__ 方法的使用——脚本之家
__EOF__

本文链接:https://www.cnblogs.com/dongye95/p/9032017.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!