• python之路 -- 面向对象基础2


    面向对象的三大特征

      ——继承,多态,封装

    继承

    继承是一种创建新类的方式,在python中新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类

     python中类的继承分为:单继承和多继承

    class ParentClass1: #定义父类
        pass
    
    class ParentClass2: #定义父类
        pass
    
    class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass
        pass
    
    class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类
        pass

     查看继承

    >>> SubClass1.__bases__ #__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类
    (<class '__main__.ParentClass1'>,)
    >>> SubClass2.__bases__
    (<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)

    提示:如果没有指定基类,python的类会默认继承object类,object是所有python类的父类

      猫可以:喵喵叫、吃、喝、拉、撒
    
      狗可以:汪汪叫、吃、喝、拉、撒
    
    如果我们要分别为猫和狗创建一个类,那么就需要为 猫 和 狗 实现他们所有的功能,伪代码如下:
    #继承的代码实现
    class Animal:
    
        def eat(self):
            print("%s 吃 " %self.name)
    
        def drink(self):
            print ("%s 喝 " %self.name)
    
        def shit(self):
            print ("%s 拉 " %self.name)
    
        def pee(self):
            print ("%s 撒 " %self.name)
    
    
    class Cat(Animal):
    
        def __init__(self, name):
            self.name = name
            self.breed = ''
    
        def cry(self):
            print('喵喵叫')
    
    class Dog(Animal):
    
        def __init__(self, name):
            self.name = name
            self.breed=''
    
        def cry(self):
            print('汪汪叫')
            
    c1 = Cat('小白家的小黑猫')
    c1.eat()
    
    #输出结果为:
    #小白家的小黑猫 吃 

    子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类)
    需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。(也就是重写父类方法)
    所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法

    新式类和经典类

    # python2.7 新式类和经典类共存,新式类要继承object
    # python3中所有类都是新式类,python3中的类默认继承object
        ——新式类继承顺序广度优先
        ——经典类继承顺序深度优先
    # 经典类和新式类还有一个区别  mro方法只在新式类中存在

    继承顺序问题

     1 class F:
     2     def func(self):
     3         print('F')
     4 class A(F):
     5     def func(self):
     6         print('A')
     7 class B(A):pass
     8     # def func(self):
     9     #     print('B')
    10 class E(F):
    11     def func(self):
    12         print('E')
    13 class C(E):
    14     def func(self):
    15         print('C')
    16 class D(B,C):
    17     pass
    18     # def func(self):print('D')
    19 
    20 d = D()
    21 d.func()    #输出的结果为:A
    22 print(D.mro())  #打印D的继承关系

     

    图一的继承顺序为:
    D->B->A->C->E->F
    图二的继承顺序为:
    D->B->A->F->C->E

    # 只要是子类的对象调用,子类中有的名字 一定用子类的,子类中没有才找父类的,如果父类也没有报错
    # 如果父类 子类都有 用子类的
        # 如果还想用父类的,单独调用父类的:
        #       父类名.方法名 需要自己传self参数
        #       super().方法名 不需要自己传self
    

     super的使用

     1 class Animal:
     2     def __init__(self,name,aggr,hp):
     3         self.name = name
     4         self.aggr = aggr
     5         self.hp = hp
     6     def eat(self):
     7         print('吃药回血')
     8         self.hp+=100
     9 
    10 class Dog(Animal):
    11     def __init__(self,name,aggr,hp,kind):
    12         super().__init__(name,aggr,hp)  #<==>Animal.__init__(self,name,aggr,hp)
    13         self.kind = kind       # 派生属性
    14     def eat(self):print('dog eating')
    15 
    16 jin = Dog('狗',200,500,'teddy')
    17 print(jin.name)
    18 jin.eat()
    19 super(Dog,jin).eat()  在外部使用super的时候需要传类和对象

    super的查找顺序和继承顺序相同
    #super 只在python3中存在
     super的本质 :不是单纯找父类 而是根据调用者的节点位置的广度优先顺序来的

     

     1 class A():
     2     def func(self): print('A')
     3 
     4 class B(A):
     5     def func(self):
     6         super().func()
     7         print('B')
     8 
     9 class C(A):
    10     def func(self):
    11         super().func()
    12         print('C')
    13 
    14 class D(B,C):
    15     def func(self):
    16         super().func()    
    17         print('D')
    18 #super的查找顺序和继承顺序相同
    19 d = D()
    20 d.func()    #输出结果为:A C B D
    21 print(D.mro())    #D->B->C->A

    接口类

    python中没有接口类,只是可以实现一个有接口类功能的类9(有抽象类)

    继承有两种用途:

    一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)

    二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能

     1 class Alipay:
     2     '''
     3     支付宝支付
     4     '''
     5     def pay(self,money):
     6         print('支付宝支付了%s元'%money)
     7 
     8 class Applepay:
     9     '''
    10     apple pay支付
    11     '''
    12     def pay(self,money):
    13         print('apple pay支付了%s元'%money)
    14 
    15 
    16 def pay(payment,money):
    17     '''
    18     支付函数,总体负责支付
    19     对应支付的对象和要支付的金额
    20     '''
    21     payment.pay(money)
    22 
    23 
    24 p = Alipay()
    25 pay(p,200)    #支付宝支付了200元

    接口类的多继承

     1 #接口类的多继承
     2 #tiger 走路 游泳
     3 #swan 走路 游泳 飞
     4 #oldying 走路 飞
     5 from abc import abstractmethod,ABCMeta    #1.引用这个模块
     6 class Swim_Animal(metaclass=ABCMeta):     #2.传入这个metaclass=ABCMeta
     7     @abstractmethod                       #3.加上此装饰器的语法糖@abstractmethod
     8     def swim(self):pass                   #满足这3点的就可以成为接口类
     9 
    10 class Walk_Animal(metaclass=ABCMeta):
    11     @abstractmethod
    12     def walk(self):pass
    13 
    14 class Fly_Animal(metaclass=ABCMeta):
    15     @abstractmethod
    16     def fly(self):pass
    17 
    18 class Tiger(Walk_Animal,Swim_Animal):
    19     def walk(self):
    20         pass
    21     def swim(self):
    22         pass
    23 
    24 class OldYing(Fly_Animal,Walk_Animal):pass
    25 class Swan(Swim_Animal,Walk_Animal,Fly_Animal):pass
    接口类的多继承
     1 from abc import ABCMeta,abstractmethod
     2 
     3 class Payment(metaclass=ABCMeta):
     4     @abstractmethod
     5     def pay(money):
     6         print("支付了%s" % money)
     7 
     8 class Wechatpay(Payment):
     9     def fuqian(money):
    10         print('微信支付了%s元'%money)
    11 
    12 # p = Wechatpay(200) #此处实例化会报错
    13 #只实例化一个类,不调用类中的方法就会报错
    14 
    15 p = Wechatpay.fuqian(200)
    16 p2 = Wechatpay.pay(100)
    17 p3 = Payment.pay(50)
    18 #执行结果:
    19 #微信支付了200元
    20 #支付了100
    21 #支付了50
     

     抽象类

    与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
    抽象类与普通类的不同之处在于:抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点类似,但其实是不同的,
    python支持抽象类,多继承。

    抽象类可以有构造方法,接口不能有构造方法;

    多态

    多态指的是一类事物有多种形态

     1 import abc
     2 class File(metaclass=abc.ABCMeta): #同一类事物:文件
     3     @abc.abstractmethod
     4     def click(self):
     5         pass
     6 
     7 class Text(File): #文件的形态之一:文本文件
     8     def click(self):
     9         print('open file')
    10 
    11 class ExeFile(File): #文件的形态之二:可执行文件
    12     def click(self):
    13         print('execute file')
    14 
    15 多态动态绑定(在继承的背景下使用时,有时也称为多态性)
    16 多态性是指在不考虑实例类型的情况下使用实例

    鸭子类型
    所谓鸭子类型,定义是‘是动态类型的一种风格‘。一个对象的特征不是由父类决定,而是通过对象的方法决定的。

    封装

    在python中用双下划线开头的方式将属性或者隐藏起来(设置成私有的)

     1 class Person:
     2     __key = 123  # 私有静态属性
     3     def __init__(self,name,passwd):
     4         self.name = name
     5         self.__passwd = passwd   # 私有属性
     6 
     7     def __get_pwd(self):         # 私有方法
     8         return self.__passwd   #只要在类的内部使用私有属性,就会自动的带上_类名
     9 
    10     def login(self):          # 正常的方法调用私有的方法
    11         self.__get_pwd()
    12 
    13 alex = Person('alex','alex3714')
    14 print(alex._Person__passwd)   # _类名__属性名(在内的外部只能通过这种方式调用私有属性和方法)
    15 print(alex.get_pwd())        #此处的调用方法会报错

     会用到私有的这个概念的场景

    1.隐藏起一个属性 不想让类的外部调用

    2.我想保护这个属性,不想让属性随意被改变

    3.我想保护这个属性,不被子类继承

  • 相关阅读:
    超强、超详细Redis数据库入门教程
    性能测试学习线路图(建议)
    性能测试分析软件汇总–开源、商业全部收集
    基于Locust、Tsung的百万并发秒杀压测案例[转]
    brew update失败提示:/System/Library/Frameworks/Ruby.framework/。。。解决方法
    XML特殊符号
    tsuang简易教程-MAC版
    【转】SQL Server获取日期或时间
    autoIT 传参数含引号
    Autoit 脚本以及 Java 调用
  • 原文地址:https://www.cnblogs.com/aberwang/p/9329398.html
Copyright © 2020-2023  润新知