zoukankan      html  css  js  c++  java
  • 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,呵,好反人类的写法
    还好我们一般不是这么变态,通常我们会将这两个定义成相同的名字,如下:都叫X
    X = type('X', (object,), dict(a = 1))

  • 相关阅读:
    SpringBoot整合RabbitMQ
    RabbitMQ消息确认机制
    RabbitMQ六种队列模式-简单队列模式
    RabbitMQ六种队列模式-工作队列模式
    RabbitMQ六种队列模式-发布订阅模式
    RabbitMQ六种队列模式-路由模式
    RabbitMQ六种队列模式-主题模式
    RabbitMQ简单介绍+Windows环境安装
    SpringBoot整合ActiveMQ发送邮件
    下载缓慢文件记录,持续更新[2019-10-29]
  • 原文地址:https://www.cnblogs.com/hjlweilong/p/12184967.html
Copyright © 2011-2022 走看看