欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python中实例化class的执行顺序示例详解

程序员文章站 2022-06-05 15:25:02
前言 本文主要介绍了关于python实例化class的执行顺序的相关内容,下面话不多说了,来一起看看详细的介绍吧 python里对类的实例化时有怎样的顺序 一般来...

前言

本文主要介绍了关于python实例化class的执行顺序的相关内容,下面话不多说了,来一起看看详细的介绍吧

python里对类的实例化时有怎样的顺序

一般来说一个类里面有类变量和方法,比如我们定义一个名为a的类

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中类变量和实例变量是不一样的,
类变量:不用实例化也可以访问。
实例变量:是动态创建的。必须实例化之后才可以访问,因为之前是不存在的。

比如下面这个例子:不实例化访问类变量

class a():
 a = 2
print(a.a)

输出:

>>>2

说了这么多,上代码。看看类继承时怎么运行的:

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

class x():
 a = 1
 def __name__(self):
 return '重写name方法' 
x =x()
print(x.__name__(), x.a)
x = type('重写name方法', (object,), dict(a = 1))
x = x()
print(x.__name__, x.a)

type动态创建实例化时,第一个参数就相当于重写了类的__name__方法。x类但__name__属性却不叫x,呵,好反人类的写法
还好我们一般不是这么变态,通常我们会将这两个定义成相同的名字,如下:都叫x
x = type('x', (object,), dict(a = 1))

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。