zoukankan      html  css  js  c++  java
  • Python 继承

    继承

    Python 中所有的类都是object类的子类,而object 继承自type

    继承分为 接口继承实现继承

    接口继承:使用父类的接口名,子类重写这个方法。尽可能的继承接口类,在子类中实现方法,鼓励对接口类的多继承,这样遵循接口隔离原则,有利于归一化设计,不提倡对抽象类进行多继承

    实现继承:子类不需要实现任何东西,直接使用父类接口和实现会增强代码的耦合性,不推荐使用

    一些细节

    类继承最终要被实例化,我们多数时候使用的还是对象而不是类。因此我们还是来一点点看继~

    继承的过程

    承仅仅是一种代码复用的手段,并不会讲代码全部的加载到子类的空间中,方法依然属于父类。下面的例子能看到,Cat.func 依然是 Animal 的,更近一步的理解,func 也仅仅是func,它只是被绑定到了类 Animal上而已,类 只是能帮我们找到这个函数,子类通过父类找到这个函数就完了~ 。

    class Animal(object):
    
        def func(self):
            print("Animal.func")
    
    
    class Dog(Animal):
    
        def func(self):
            print('Dog.func')
    
    
    class Cat(Animal):
        """ No func~ """
    
    
    print(Animal.func)   # <function Animal.func at 0x103f79620>
    print(Cat.func)   # <function Animal.func at 0x103f79620>
    print(Dog.func)   # <function Dog.func at 0x104073510>
    

    实例化的过程

    实例化过程中属性和方法并不会出现在实例的空间里。它们依然属于类本身,对象也只是能找到他们,然后调用他们。但是当修改对象的属性时,会在对象的空间中创建同名的属性。这是属于对象的属性。 复杂的继承其本质也是一样的。

    class Animal(object):
    
        def tell(self):
            print('self.name:%s Animal.name %s ' % (id(self.name), id(Animal.name)))
    
        name = 'Animal'
    
    
    class Cat(Animal):
        """ No func~ """
    
        def tell(self):
            super().tell()
            print('self.name %s Cat.name %s '% (id(self.name), id(Cat.name)))
    
    cat = Cat()
    cat.tell()
    cat.name = 'django'
    cat.tell()
    
    # self.name:4473398472 Animal.name 4473398472 
    # self.name 4473398472 Cat.name 4473398472 
    # self.name:4474859736 Animal.name 4473398472 
    # self.name 4474859736 Cat.name 4473398472 
    

    单继承

    越靠近本类的方法会覆盖祖辈的方法,这叫方法的覆盖或重写 原理是 Python的属性检索机制 从内层命名空间往外查询

    class MyClass(object):
        """
        A simple example class
        """
        MyClassName = 'MyClass'
        name = 'MyClass'
    
        def func(self):
            print("This is {}".format(self.__class__.name))
    
        def get_name(self):
            print(self.name)
    
    class MySonClass(MyClass):
    
        MySonClass = 'MySonClass'
        name = 'MySonClass'  # 属性的重写
    
        def get_name(self):
            super().get_name()
            print('我重写了父类的get_name方法,上面是父类的方法,我来自子类!')
    
    
    person1 = MyClass()
    person2 = MySonClass()
    
    person1.func()
    person2.func()    # 方法的实现继承 自己没有,会直接调用父类的方法。但是使用的属性还是自己的。
    print('*'*40)
    person1.get_name()
    person2.get_name()    # 方法的接口继承,在子类中重写了这个方法。
    
    
    # 结果	
    #------------------------------ 
    # This is MyClass
    # This is MySonClass
    # ****************************************
    # MyClass
    # MySonClass
    # 我重写了父类的get_name方法,上面是父类的方法,我来自子类!
    

    多继承

    就形式上来说,类的继承列表可以是一个,也可以是多个,当继承列表只有一个类时,也就是只有一个父类时,称为单继承,大于一个类,就称为多继承。

    新式类的继承方式为 广度优先继承 经典类的继承方式为 深度优先继承

    类继承的顺序可以使用类的 __mro__ 方法查看。

    钻石继承

    class A(object):
        m = 'a'
    class B(A):
        m = 'b'
    class C(A):
        m = 'c'
    class D(B,C):
        # m = 'd'
        pass
    x = D()
    print(x.m)
    
    # D 的实例化对象如果获取 m 属性会优先的寻找自己的命名空间,查找顺序为 D -> B -> C -> A
    

    super()方法

    语法super(类,实例化对象).父类的方法

    • super()方法在类的内部使用时候,甚至不需要任何的参数

    • 当在多继承中使用super()方法的时候执行的不再是父类的方法了 而是和mro中上一级的方法

    • super()为了解决多继承中,初始化方法被重复调用的问题。(当使用类名.方法名的时候)

    • 当使用super()方法执行“父类” (__mro__ 方法的上一个类) 的方法

    # 钻石继承中的 重复调用问题
    # 注意 继承的查找顺序~ 使用super()将按照 mro 顺序执行
    
    class Grand(object):
        def __init__(self, name):
            self.name = name
            print("class Grand ")
    
    
    class SonLeft(Grand):
        def __init__(self, age, name):
            self.age = age
            Grand.__init__(self, name) # 注释调 跑一跑 看一看
            # super().__init__(age, name)
            print("class SonLeft")
    
    
    class SonRight(Grand):
        def __init__(self, gender, name):
            self.gender = gender
            Grand.__init__(self, name) # 注释调 跑一跑 看一看
            # super().__init__(name)
            print("class SonRight")
    
    
    class GrandSon(SonLeft, SonRight):
        def __init__(self, name, age, gender):
            # super().__init__(age, name)
            SonLeft.__init__(self, age, name)  # 注释调 跑一跑 看一看
            SonRight.__init__(self, gender, name)  # 注释调 跑一跑 看一看
            self.gender = gender
    
    grand_son = GrandSon("Monkey", 18, "男")
    
  • 相关阅读:
    DNS原理总结及其解析过程详解
    linux修改进程名
    mq_open失败,Invalid argument
    Posix消息队列
    undefined reference to 'mq_open'
    量化投资学习笔记08——统计学基础补漏
    量化投资学习笔记07——python知识补漏
    量化投资学习笔记06——《打开量化投资的黑箱》读书笔记
    量化投资学习笔记05——检验计算回测指标程序
    量化投资学习笔记04——回测实盘策略
  • 原文地址:https://www.cnblogs.com/monkey-code/p/13158981.html
Copyright © 2011-2022 走看看