zoukankan      html  css  js  c++  java
  • Python面向对象之继承

    一、继承

    面向对象的语言:c++,c#,java

    面对对象的三大特性(继承、多态、封装) 其他语言都有

     

    二、继承和抽象

    实例---> 分类 ---> 汇总      逐渐抽象

    编程实现:先抽象,后继承

     

    继承的好处:继承能提高代码的重用性,还能规范代码

     

    继承分为子类和父类

    父类/超类/基类

    子类/派生类

    class Animal:                     # 父类
        def __init__(self,name,kind):
            self.name = name
            self.kind = kind
    
        def sleep(self):
            print('%s在睡觉'% self.name)
    
    class Cat(Animal):                  # 子类
        def catch(self):
            print('%s抓老鼠'% self.name)
    
    cat = Cat('小猫','咖啡猫')
    print(cat.name)
    cat.sleep()
    cat.catch()
    
    ------------------
    小猫
    小猫在睡觉
    小猫抓老鼠
    ------------------

     

    继承的语法:

    class A:pass

    class B(A):pass

    class A:            # 父类
        ...
    class B(A):         # B 继承 A
        ...

     

    三、单继承

    继承与重用

    重用:子类可以使用父类中的所有属性和方法,父类中所有的属性和方法都可以被子类使用了

          子类可以使用父类中的名字(变量和方法)

    class Animal:                     # 父类
        def __init__(self,name,kind):
            self.name = name
            self.kind = kind
    
        def sleep(self):
            print('%s在睡觉'% self.name)
    
    class Cat(Animal):                  # 子类
        def catch(self):
            print('%s抓老鼠'% self.name)
    
    class Dog(Animal):
        def walk_the_dog(self):
            print('溜%s' % self.name)
    
    cat = Cat('小猫','咖啡猫')
    dog = Dog('小狗','导盲犬')
    cat.sleep()
    dog.sleep()
    
    -----------------
    小猫在睡觉
    小狗在睡觉
    -----------------

     

    派生

    子类在父类的基础上又新创新了自己需要的方法和属性

    ① 父类有的子类没有--- 子类对象直接调用,就会直接执行父类的方法

    ② 父类有的子类也有--- 子类对象调用 直接执行子类中的方法

                                     ---  在子类中使用父类的名字:父类名、super()

    class Animal:
        def __init__(self,name,kind):
            self.name = name
            self.kind = kind
    
        def drink(self):
            print('%s在喝水'% self.name)
    
    class Cat(Animal):                              # 派生类
        def __init__(self,name,kind,eye_color):
            self.name = name
            self.kind = kind
            self.eye_color = eye_color              # 派生属性
    
        def catch(self):                            # 派生方法
            print('抓老鼠')

    当子类当中有被调用的方法的时候,子类的对象会直接选择子类中的方法或者变量,父类中的方法不会被执行

     

    方法一:子类已存在同名的方法,调用父类的方法

    class Animal:
        def __init__(self,name,kind):
            self.name = name
            self.kind = kind
    
        def drink(self):
            print('%s在喝水'% self.name)
    
    class Cat(Animal):                              # 派生类
        def __init__(self,name,kind,eye_color):
            Animal.__init__(self,name,kind)         # 调用父类的方法
            self.eye_color = eye_color              # 派生属性
    
        def catch(self):                            # 派生方法
            print('抓老鼠')

     

    方法二:子类已存在同名的方法,调用父类的方法

    class Animal:
        def __init__(self,name,kind):
            self.name = name
            self.kind = kind
    
        def drink(self):
            print('%s在喝水'% self.name)
    
    class Cat(Animal):                              # 派生类
        def __init__(self,name,kind,eye_color):
            # Animal.__init__(self,name,kind)         # 调用父类的方法,要加参数self
            super().__init__(name,kind)               # 调用父类的方法,super不需要加self  
            self.eye_color = eye_color              # 派生属性
    
        def catch(self):                            # 派生方法
            print('抓老鼠')

     

    子类和父类有同名的方法,如果既要执行子类的方法,也想要执行父类的方法,那么需要在子类的方法中调用父类的方法:

    ①父类名.方法名(self)

    ② super().方法名()

    super()调用父类的方法,不需要传self,通过父类名调用父类的方法要传self

     

    class Foo:
        def __init__(self):
            self.func()
        def func(self):
            print('in Foo')
    
    class Son(Foo):
        def func(self):
            print('in Son')
    s1 = Son()
    
    '''
    结果:in Son
    '''

    self = s1,调用的是Son自己的方法func,所以执行的是子类自身的方法

    当self去调用某个方法的时候,不要看self在哪个类里,要看self到底是谁

     

    class Foo:
        city = 'ShenZhen'
        def func(self):
            print(self.city)
    
    class Son(Foo):
        city = 'HONGKONG'
    
    s = Son()
    s.func()
    
    '''
    结果  HONGKONG
    '''

    s.func()执行的是父类中的方法,但是调用的属性是Son本身的属性,self就是s,打印的是Son的属性

    当self去调用某个方法的时候,不要看self在哪个类里,要看self到底是谁

     

    四、抽象类

    抽象类的一个特点是它不能直接被实例化

    抽象类的目的就是让别的类继承它并实现特定的抽象方法

    抽象基类的一个主要用途是在代码中检查某些类是否为特定类型,实现了特定接口

     

    抽象类的场景:

    ① 工作中公司有使用抽象类开发的规则

    ② 看源码,别人的源码使用了抽象类

    python使用抽象类的不多

     

    抽象类用来规范代码:

    多人开发,复杂的需求、后期的扩展和版本的更新,用新的手段(抽象)来完成规范

     

    抽象类的描述:

    抽象类是一个规范,它基本不会实现具体的功能,是由于抽象类不能被实例化

     

    写抽象类:

    from abc import ABCMeta,abstractmethod

    在这个类创建的时候指定metaclass=ABCMeta

    在子类实现的方法加上一个@abstractmethod 装饰器

    from abc import ABCMeta,abstractmethod
    
    class Payment(metaclass=ABCMeta):
        @abstractmethod                 # abstractmethod 是一个装饰器,装饰器放在函数/类的上一行
        def pay(self):
            pass
    
    class GooglePay(Payment):
        def pay(self,money):
            print('支付了%s元'% money)
    
    def pay(obj,money):
        obj.pay(money)
    
    G = GooglePay()
    a = pay(G,10000)
    
    '''
    支付了10000元
    '''

     

    装饰器一般放在函数或者类的上一行,表示装饰下一行的函数或者类

    使用装饰器:

    ① 继承这个类

    ② 必须实现这个类(子类创建同名的方法)被abstractmethod 装饰器 装饰的方法

    定义了抽象类必须实行抽象方法,否则会报错

     

    五、多继承

    不支持的继承的语言:java,C#

    支持多继承的语言:C++,python

    多继承的弊端:继承的父类有同名的方法

     

    多继承的定义:python一个子类可以调用多个父类的方法

    class Animal:
        def __init__(self,name):
            self.name = name
    
    class Land(Animal):
        def walk(self):
            print('%s 在步行'% self.name)
    
    class Sea(Animal):
        def swim(self):
            print('%s 在游泳'% self.name)
    
    class Air(Animal):
        def fly(self):
            print('%s 在飞行'% self.name)
    
    class Drogon(Land,Sea,Air):
        pass
    
    class Frog(Sea,Land):
        pass
    
    drogon = Drogon('东海龙')
    drogon.fly()
    drogon.swim()
    drogon.walk()
    
    '''
    东海龙 在飞行
    东海龙 在游泳
    东海龙 在步行
    '''

     

    六、接口类

    java C# 接口可以被多继承,接口的方法不能有代码。

    不允许类的多继承语言,规范继承类必须实现这个方法。

     

    python 中没有接口,抽象类相当于接口

     

    七、新式类和经典类

    新式类:python3的版本中,所有的类都是新式类

    所有的新式类都有一个默认的父类:object

    class Person1:pass              # 定义类的写法1
    class Person2():pass            # 定义类的写法2
    class Person3(object):pass      # 定义类的写法3
    
    print(Person1.__bases__)
    print(Person2.__bases__)
    print(Person3.__bases__)
    
    '''
    (<class 'object'>,)
    (<class 'object'>,)
    (<class 'object'>,)
    '''

     

    定义类的三种写法:

    ① 类名:

    ② 类名():

    ③ 类名(object):

     

    python2.7版本是经典类和新式类并存

    继承了object的类就是新式类:

    python3中所有的类都是新式类

    python2.7既有新式类又又经典类

    不主动继承object都是经典类

    新式类和经典类之间多继承顺序的区别:

    新式类:

      所有的多继承关系寻找方法的顺序是---遵循广度优先算法

      ① 走过的路不能重复

      ② 所有的点都要走到

      新式类中可以使用类.mro() 查看继承顺序

      super() 不是单纯的找父类,而是遵循mro顺序的

    经典类:

      经典类在找父类中方法的过程中---遵循 深度优先

      深度优先:①一条路走到底

              ② 走过的路不走

    class A:pass
    class B(A):pass
    class C(A):pass
    class D(B,C):pass
    
    print(D.mro())
    
    '''
    [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
    '''

    super() 不是单纯的找父类,而是遵循mro顺序的

    class A:
        def func(self):
            print('A')
    class B(A):
        def func(self):
            super().func()
            print('B')
    class C(A):
        def func(self):
            super().func()
            print('C')
    class D(B,C):
        def func(self):
            super().func()
            print('D')
    
    print(D.mro())
    D().func()
    
    
    '''
    [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
    A
    C
    B
    D
    '''

    新式类与经典类的区别:

    新式类:

    ①所有的多继承关系寻找方法的顺序---遵循广度优先算法

    ②继承object

    ③mro方法

    ④super(): super不是单纯的找父类,而是遵循mro顺序的

    经典类:

    ① python2版本

    ② 不主动继承object

    ③ 经典类在找父类中方法的过程中 遵循---深度优先

    ④ 不提供mro方法和super()

  • 相关阅读:
    mysql的cmd窗口查看数据库信息
    常见抓包工具
    图形数据库
    支付宝支撑双十一4200万次/秒的数据库请求峰值的技术实现
    处理tomcat内存溢出问题
    maven将jar包打如本地仓库命令
    fastJson去掉指定字段
    mybatis insert 返回主键
    maven引入源码
    mysql实现主从复制
  • 原文地址:https://www.cnblogs.com/st-st/p/9549379.html
Copyright © 2011-2022 走看看