• Python中super的用法(新式类与经典类(旧式类)的区别)


    楼主初学Python一星期,在书上遇到一个super的问题,便开始找寻python  super相关的资料,楼主吧网上关于super的代码复制到编辑器里运行,结果出来TypeError: super() argument 1 must be type, not classobj。如上的错误,楼主又开始找寻这个错误相关的资料,发现基本上的资料都是直接告诉我————在python2.2版本之前,直接调用超类的方法,后来改成通过super来调用,原因是为了解决多重继承中的钻石形状问题。Python里的super只能用在新式类中,不能用于以前的经典类,如果基类是经典类则会出现这个错误。解决的方法是FatherClass只要有一个超类是Object就OK了。当时我就很蒙蔽,于是再次寻找新式类与经典类的区别。经过自己敲代码终于有所悟。

          首先区分新式类与经典类的区别,经典类即在没有父类的情况下直接写成class A,而新式类则必须写成class A(object),其中(object)有否是区别新式类与经典类的关键,而super执行时必须为新式类。如果你缺少了(object),则class A就变成了经典类而无法初始化super,从而会产生报错TypeError: super() argument 1 must be type, not classobj。接下来是两段简单的代码理解新式类与经典类的区别。同时你可以把代码2中的第一条语句class A(object):改成class A:再运行下看看会不会报错。我想这能更好的帮助你理解新式类与经典类的区别同时更好的使用super。

    代码1:

    class A:
        def __init__(self):
            print("Enter A")
            print("Leave A")

    class B(A):
        def __init__(self):
            print("Enter B")
            A.__init__(self)
            print("Leave B")

    class C(A):
        def __init__(self):
            print("Enter C")
            A.__init__(self)
            print("Leave C")

    class D(A):
        def __init__(self):
            print("Enter D")
            A.__init__(self)
            print("Leave D")

    class E(B, C, D):
        def __init__(self):
            print("Enter E")
            B.__init__(self)
            C.__init__(self)
            D.__init__(self)
            print("Leave E")
            
    E()

    很显然,代码1的运行结果为

    Enter E
    Enter B
    Enter A
    Leave A
    Leave B
    Enter C
    Enter A
    Leave A
    Leave C
    Enter D
    Enter A
    Leave A
    Leave D
    Leave E

    改代码为逐语句执行所给代码,及深度优先搜索。公共父类A被多次执行。



    代码2:

    class A(object):
        def __init__(self):
            print("Enter A")
            print("Leave A")

    class B(A):
        def __init__(self):
            print("Enter B")
            super(B, self).__init__()
            print("Leave B")

    class C(A):
        def __init__(self):
            print("Enter C")
            super(C, self).__init__()
            print("Leave C")

    class D(A):
        def __init__(self):
            print("Enter D")
            super(D, self).__init__()
            print("Leave D")

    class E(B, C, D):
        def __init__(self):
            print("Enter E")
            super(E, self).__init__()
            print("Leave E")

    E()


    代码2的运行结果为:

    Enter E
    Enter B
    Enter C
    Enter D
    Enter A
    Leave A
    Leave D
    Leave C
    Leave B
    Leave E

    采用的是广度优先搜索,即在遇到super(E, self).__init__()是直接桉序进入B,C,D,而不是进入B之后吧B执行完了再退回来执行C,因此在进入B,C,D后三个类都要执行公共父类A,三者所做的事情是一样的,所以父类A只被执行一次。因此获得如上结果。



    从运行结果上看,普通继承和super继承是一样的。但是其实它们的内部运行机制不一样,这一点在多重继承时体现得很明显。在super机制里可以保证公共父类仅被执行一次,至于执行的顺序,是按照mro进行的(E.__mro__)。
    注意:super继承只能用于新式类,用于经典类时就会报错。
    新式类:必须有继承的类,如果没什么想继承的,那就继承object
    经典类:没有父类,如果此时调用super就会出现错误:『super() argument 1 must be type, not classobj』

    更详细的参考

    http://blog.csdn.net/johnsonguo/article/details/585193

    总结
      1. super并不是一个函数,是一个类名,形如super(B, self)事实上调用了super类的初始化函数,
           产生了一个super对象;
      2. super类的初始化函数并没有做什么特殊的操作,只是简单记录了类类型和具体实例;
      3. super(B, self).func的调用并不是用于调用当前类的父类的func函数;
      4. Python的多继承类是通过mro的方式来保证各个父类的函数被逐一调用,而且保证每个父类函数
           只调用一次(如果每个类都使用super);
      5. 混用super类和非绑定的函数是一个危险行为,这可能导致应该调用的父类函数没有调用或者一
           个父类函数被调用多次。



    转载自  http://blog.csdn.net/cairns0214/article/details/51891749



  • 相关阅读:
    WPF基础篇之控件模板(ControlTemplate)
    WPF基础篇之移动特效
    WPF基础篇之空间布局
    00-API-Mongoose
    00-API-Vue
    博客园皮肤设置
    15-Node
    16-Vue-A
    15-MongoDB
    14-电商项目
  • 原文地址:https://www.cnblogs.com/360linux/p/13062104.html
Copyright © 2020-2023  润新知