• python类中super()与__init__()


    子类继承的初始化规则

    首先需要说明关于类继承方面的初始函数__init__()

    • 如果子类没有定义自己的初始化函数,父类的初始化函数会被默认调用,但是需要在实例化子类的对象时传入父类初始化函数对应的参数
    • 如果子类定义了自己的初始化函数,而在子类中没有显式调用父类的初始化函数,则父类的属性不会被初始化,
    • 如果子类定义了自己的初始化函数,在子类中显示调用父类,子类和父类的属性都会被初始化

    对于情况1,如下:

    class Base:
        def __init__(self, name, id = 2):
            self.name = name
            self.id = id
            print("Base create")
            print("id = ", self.id)
        def func(self):
            print("base fun")
    class childA(Base):
        # def __init__(self):
        #     print("childA create")
            # Base.__init__(self, "A")        # 父类名硬编码到子类中
        def funA(self):
            print("funA")
    
    A = childA('john',id=2) # 必须手动传入,否则A还是不会有name和id对象
    print(A.name, A.id)
    

    结果为:

    Base create
    id =  2
    john 2
    

    对于情况2,如下:

    class Base:
        def __init__(self, name, id = 2):
            self.name = name
            self.id = id
            print("Base create")
            print("id = ", self.id)
        def func(self):
            print("base fun")
    class childA(Base):
        def __init__(self):
            print("childA create")
            # Base.__init__(self, "A")        # 父类名硬编码到子类中
        def funA(self):
            print("funA")
    
    A = childA()
    print(A.name, A.id)
    

    结果显示为:

    AttributeError: 'childA' object has no attribute 'name'
    

    对于情况3,如下:

    class Base:
        def __init__(self, name, id = 2):
            self.name = name
            self.id = id
            print("Base create")
            print("id = ", self.id)
        def func(self):
            print("base fun")
    class childA(Base):
        def __init__(self):
            print("childA create")
            Base.__init__(self, "A")        # 父类名硬编码到子类中
        def funA(self):
            print("funA")
    

    结果为:

    Base create
    id =  2
    john 2
    

    其中Base.__init__(self, "A")就是朴素的子类调用父类的初始化,初始化时必须填入位置变量name即这里的"A",而关键字变量id可选。

    super()

    注意super()只能用在新式类中(当然用python3的人不用担心这个问题),并且在单继承类中super()跟单纯的__init__()没什么区别,如下:

    class Base:
        def __init__(self, name, id = 2):
            self.name = name
            self.id = id
            print("Base create")
            print("id = ", self.id)
        def func(self):
            print("base fun")
            
    class childA(Base):
        def __init__(self):
            print("childA create")
            Base.__init__(self, "A")        # 父类名硬编码到子类中
        def funA(self):
            print("funA")
            
    class childB(Base):
        def __init__(self):
            print("childB create")
            # super(childB, self).__init__('B')    # super,将子类名和self传递进去
            super().__init__('B',id=3) # python3可以直接简化成这个形式
            self.id = 3
    

    另外需要注意的是super不是父类,而是继承顺序的下一个类,如下是多类继承的情况:

    class Base(object):
        def __init__(self):
            print 'Base create'
    
    class childA(Base):
        def __init__(self):
            print 'enter A '
            # Base.__init__(self)
            super(childA, self).__init__()
            print 'leave A'
    
    
    class childB(Base):
        def __init__(self):
            print 'enter B '
            # Base.__init__(self)
            super(childB, self).__init__()
            print 'leave B'
    
    class childC(childA, childB):
        pass
    
    c = childC()
    print c.__class__.__mro__
    

    输出结果如下:

    enter A 
    enter B 
    Base create
    leave B
    leave A
    (<class '__main__.childC'>, <class '__main__.childA'>, <class '__main__.childB'>, <class '__main__.Base'>, <type 'object'>)
    

    supder和父类没有关联,因此执行顺序是A —> B—>—>Base,执行过程相当于:初始化childC()时,先会去调用childA的构造方法中的 super(childA, self).init(), super(childA, self)返回当前类的继承顺序中childA后的一个类childB;然后再执行childB().init(),这样顺序执行下去。

    在多重继承里,如果把childA()中的 super(childA, self).init() 换成Base.init(self),在执行时,继承childA后就会直接跳到Base类里,而略过了childB:

    enter A 
    Base create
    leave A
    (<class '__main__.childC'>, <class '__main__.childA'>, <class '__main__.childB'>, <class '__main__.Base'>, <type 'object'>)
    

    super()复杂示例

    下面举一个更复杂的例子帮助更好的理解super():

    class Rectangle:
        def __init__(self, length, width):
            self.length = length
            self.width = width
    
        def area(self):
            return self.length * self.width
    
        def perimeter(self):
            return 2 * self.length + 2 * self.width
    
    class Square(Rectangle):
        def __init__(self, length):
            super(Square, self).__init__(length, length)
    class Triangle:
        def __init__(self, base, height):
            self.base = base
            self.height = height
    
        def area(self):
            return 0.5 * self.base * self.height
    
    class RightPyramid(Triangle, Square):
        def __init__(self, base, slant_height):
            self.base = base
            self.slant_height = slant_height
    
        def area(self):
            base_area = super().area()
            perimeter = super().perimeter()
            return 0.5 * perimeter * self.slant_height + base_area
    
  • 相关阅读:
    关于winform动态创建button等控件以及规定行列
    Winform调用系统计算器、记事本
    悲催的一晚
    C#winform从数据集导出Excel(带指定Excel样式) 转+修改
    C#一列数的规则如下: 1、1、2、3、5、8、13、21、34...... 求第100位数是多少, 用递归算法实现。
    C#任意输入一个数,判断这个数是否跟数组里的数相等
    构建一个web应用系统应该分为哪几个步骤
    ios XMPP GCDAsynSocket线程溢出挂掉程序
    Error Domain=NSCocoaErrorDomain Code=3000 "未找到应用程序的“apsenvironment”的权利字符串" UserInfo=0x22f6a0 {NSLocalizedDescription=未找到应用程序的“apsenvironment”的权利字符串
    ios推送php服务器端pem文件
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13281629.html
Copyright © 2020-2023  润新知