Python中实例化class的执行顺序示例详解
前言
本文主要介绍了关于Python实例化class的执行顺序的相关内容,下面话不多说了,来一起看看详细的介绍吧
Python里对类的实例化时有怎样的顺序
一般来说一个类里面有类变量和方法,比如我们定义一个名为A的类
1
2
3
4
5
|
class A(): bar = "my lover love me" def __init__( self , name): print ( 'A的class' , self .__class__, name) |
我们在这个类里面定义了一个类变量bar和一个构造方法__init__,那么我们实例化A()时都发生了什么呢!看官不要急,听我慢慢道来...
- 首先,python 调用内置的type类,没有听错,就是我们平时用来测引用类型的那个type,然后type调用内置的元类mateClass,mateClass再调用__new__方法将类实例化,此时完成了第一步
- 然后,这个实例将会初始化自己的类变量,就是把自己从头到尾扫视一遍,
- 之后,进入构造方法,并初始化自己的实例变量。
注意:python中类变量和实例变量是不一样的,
类变量:不用实例化也可以访问。
实例变量:是动态创建的。必须实例化之后才可以访问,因为之前是不存在的。
比如下面这个例子:不实例化访问类变量
1
2
3
|
class A(): a = 2 print (A.a) |
输出:
>>>2
说了这么多,上代码。看看类继承时怎么运行的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class A(): def __init__( self , name): print ( 'A的class' , self .__class__, name) class B(A): def __init__( self , name): self ._name = name A.__init__( self , name) print ( 'B的class' , self .__class__, name) print ( 'this is B class' ) class C(B): def __init__( self , name): B.__init__( self , name) print ( 'C的class' ) if __name__ = = '__main__' : c = C( 'lee' ) |
输出如下:
this is B class
A class <class '__main__.C'> lee
B class <class '__main__.C'> lee
C class
来现身说法,解释一波
- 首先对class C()进行实例化,从头到尾扫一遍,然后进入C()的构造,遇到了父类C()的构造方法B.__init__ 。
- 进入class B(),从头到尾扫一遍,执行了
print('this is B class')
语句然后进入B()的构造,遇到了父类B()的构造方法A.__init__。 - 进入class A(),从头到尾扫一遍,然后进入A()的构造方法A.__init__。然后A.__init__执行完毕并弹出栈,class A()执行完毕并弹出栈。
- 回到class B(),从上次未执行完的地方
print('B的class', self.__class__, name)
继续执行。然后B.__init__执行完毕并弹出栈,class B()执行完毕并弹出栈。 - 回到class C(),从上次未执行完的地方
print('C的class')
继续执行。然后C.__init__执行完毕并弹出栈,class C()执行完毕并弹出栈。程序运行完毕。 - 由于是对class C()进行实例化,上面的self都是指class C()的实例而不是class A()的或者class B()的。因此self.__class__清一色的显示
<class '__main__.C'>
而不是<class '__main__.A'>
或<class '__main__.B'>
。
随便补充一下使用type关键字动态创建类的知识点,敲黑板、、、我要用CET3.5的英语水平向大家翻译一部分官方文档对type的描述啦。
使用三个参数,返回一个新类型对象。这实际上是类语句的动态形式。名称字符串是类名,并成为__name__属性;基元元组列出基类并成为>__bases__属性;并且dict字典是包含类主体定义的命名空间,并被复制到标准字典以成为__dict__属性。
怎么样,是不是很拗口,是不是大写的懵*。so,上代码,以下两种写法输出一样的都是输出:重写name方法 1
1
2
3
4
5
6
|
class X(): a = 1 def __name__( self ): return '重写name方法' x = X() print (x.__name__(), x.a) |
1
2
3
|
X = type ( '重写name方法' , ( object ,), dict (a = 1 )) x = X() print (X.__name__, x.a) |
type动态创建实例化时,第一个参数就相当于重写了类的__name__方法。X类但__name__属性却不叫X,呵,好反人类的写法
还好我们一般不是这么变态,通常我们会将这两个定义成相同的名字,如下:都叫XX = type('X', (object,), dict(a = 1))
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2019-01-12 降息?