zoukankan      html  css  js  c++  java
  • 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
    
  • 相关阅读:
    Python 函数式编程学习
    Perl 学习笔记-目标操作
    Ubuntu14.04-LTS 从系统安装到配置可用
    Perl 学习笔记-文件测试
    Perl 学习笔记-模块
    插曲 强大的神器 vmware
    18 11 16 网络通信 ---- 多线程 同步概念 解决资源互斥的问题
    18 11 15 网络通信 ---- 多任务----线程 threading
    18 11 14 案例 下载文件后端编写
    18 11 13 装了ssd 继续 网络通信 tcp 客户端的创建
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13281629.html
Copyright © 2011-2022 走看看