python笔记(19)--面向对象三大特性补充

内容目录:

  • 继承
  • 多态
  • 封装

内容回顾

  • 面向对象编程:

    • 思想:角色的抽象,创建类,创建角色(实例化),操作这些实例

    • 面向对象的关键字

    • #示例:
      class Object:		#类名首字母大写
          name = 'lyn'
          def __init__(self):pass
      
      Object.name		#存储在类的命名空间里
      obj = Object()		#实例化:创造一个self对象,执行init方法,返回self对象给obj
      
      #对象.属性
      #对象.方法   相等于    类名.方法(对象)
      #对象可以使用静态变量吗?	True
      #类可以使用对象的属性吗?	False
      
    • 组合(最起码是两个类)

      • 一个类的对象是另外一个类对象的属性

      • class A:
            def __init__(self):
                self.name = 'alec'
         
        class B:
            def __init__(self,year,month,day):
                self.year = year
                self.month = month
                self.day = day
                
        b = B(19, 1, 17)
        print(b.year,b.month,b.day)
        a = A()
        a.birth = b
        print(a.birth.year)
        

内容详细:

1.继承

1.1 单继承

  • 类和类之间才能被称为继承,类和对象之间只能是实例化

  • 一个类可以被多个类继承 ----只在python里适用

    class A:pass        #父类,基类,超类
    class B:pass        #父类,基类,超类
    
    class A_son(A):pass #子类,派生类
    class AB_son(A,B):pass  #可以继承多个父类
    
    #查看继承的父类
    print(A_son.__bases__)      #(<class '__main__.A'>,)
    print(AB_son.__bases__)     #(<class '__main__.A'>, <class '__main__.B'>)
    
  • 新式类:python3里所有的类都有父类,如果没有标识继承的父类,那它就是 object 的子类

  • 继承示例:

    # 把Dog和Person类中的同样的变量提取至Animal类中
    class Animal:
        def __init__(self,name,aggr,hp):
            self.name = name
            self.aggr = aggr
            self.hp = hp
    
    # 继承Animal类,可以使用父类中的变量
    class Dog(Animal):
        def bite(self,person):
            person.hp -= self.aggr
    
    class Person(Animal):
        pass
    
    #正常传值和调用
    jin = Dog('史努比',200,500)
    print(jin.name)
    
  • 面试题:

    class Animal:
        def __init__(self):
            print('执行Animal.__init__')
            self.func()
        def eat(self):
            print('%s eating'%(self.name,))
        def drink(self):
            print('%s drink' % (self.name,))
        def func(self):
            print('Animal.func')
    
    class Dog(Animal):
        def guard(self):
            print('guard')
        def func(self):
            print('Dog.func')
    
    dog = Dog()
    #结果为:
    # 执行Animal.__init__
    # Dog.func
    

1.2 派生属性

  • 派生属性:继承父类中的变量,然后自己也创建了一些特有属性

    class Animal:
        def __init__(self,name,blood,aggr):
            self.name = name
            self.blood = blood
            self.aggr = aggr
    
    class Dog(Animal):
        def __init__(self,name,blood,aggr,kind):
            Animal.__init__(self,name,blood,aggr)	#调用了父类的属性
            self.kind = kind        #自己创建的,属派生属性
    
  • 派生方法:父类中没有的方法,在子类中出现,叫做派生方法

    • 只要是子类的对象调用,子类中有的方法一定用子类的,子类中没有才能去找父类的,都没有则报错
    • 如果既想实现新功能也想适用父类的功能,还需在子类中调用父类的方法
    class Animal:
        def __init__(self,name,blood,aggr):
            self.name = name
            self.blood = blood
            self.aggr = aggr
        def eat(self):
            print('生命值增加100点')
            self.blood += 100
    
    class Dog(Animal):
        def __init__(self,name,blood,aggr,kind):
            Animal.__init__(self,name,blood,aggr)
            self.kind = kind
        def eat(self):
            Animal.eat(self)    #自己有并还想用父类的,则调用父类方法
            self.aggr += 10
        def bite(self,person):
            person.blood -= self.aggr
            print('狗咬人,人剩了%s血'%(person.blood))
    
    jin = Dog('金老板',100,20,'teddy')
    jin.eat()
    print(jin.blood,jin.aggr)
    

总结:

  • 父类中没有的属性,在子类中出现,叫做派生属性
  • 父类中没有的方法,在子类中出现,叫做派生方法
  • 只要是子类的对象调用,子类中有的方法一定用子类的,子类中没有才能去找父类的,都没有则报错
  • 如果子类调用的方法自己有并还想用父类的,单独调用父类的,需要自己传self方法

1.3 关键字super的用法:只能在新式类中使用

  • super的内部用法,相等于调用父类的init方法

  • super的外部用法,只调用父类的方法: super(子类名,实例化对象).父类中的方法

    class Animal:
        def __init__(self,name,blood,aggr):
            self.name = name
            self.blood = blood
            self.aggr = aggr
        def eat(self):
            print('生命值增加100点')
            self.blood += 100
    
    class Dog(Animal):
        def __init__(self,name,blood,aggr,kind):
            super().__init__(name,blood,aggr)      #内部使用super方法,相等于Animal.__init__(self,name,blood,aggr)
            self.kind = kind
        def eat(self):
            self.aggr += 10
        def bite(self,person):
            person.blood -= self.aggr
            print('狗咬人,人剩了%s血'%(person.blood))
    
    jin = Dog('金老板',100,20,'teddy')
    jin.eat()                   #只调用自己的方法
    super(Dog,jin).eat()        #super用法:只调用父类的方法
    print(jin.blood,jin.aggr)
    

1.4 多继承

  • 多继承中,我们子类的对象调用一个方法,默认是就近原则

    class A:
        def func(self):print('A')
    class B:
        def func(self):print('B')
    class C(A,B):					#继承父类时,先找A,再找B,顺序查找
        # def func(self):print('C')
        pass
    
    c = C()
    c.func()						#结果为A
    
  • 查看继承关系: 对象.mor()

    #接上面列子
    print(C.mro())  
    #[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
    
  • 钻石继承

    • py2中经典类中遵循深度优先,py3中新式类遵循广度优先

  • 多继承

2.多态

  • 接口类和抽象类 在python当中的应用点并不是非常必要的

    • 使用abc模块来规范子类,必须有父类中的方法
    import abc
    class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
        @abc.abstractmethod
        def talk(self):
            pass
    
    class People(Animal): #动物的形态之一:人
        def talk(self):
            print('say hello')
    
    class Dog(Animal): #动物的形态之二:狗
        def talk(self):
            print('say wangwang')
    
    class Pig(Animal): #动物的形态之三:猪
        def talk(self):
            print('say aoao')
    
  • 因为python中不崇尚用父类约束子类的方法,因为python当中有鸭子类型

3.封装

3.1 类中私有

  • 所有的私有,都是在变量的左边加上双下划线

    • 对象的私有属性
    • 类中的私有方法
    • 类中的静态私有属性
  • 所有的私有的,都不能在类的外部使用

    class Person:
        __key = 123                     # 私有静态属性
        def __init__(self,name,passwd):
            self.name = name
            self.__passwd = passwd      # 私有属性
    
        def __get_pwd(self):            # 私有方法
            # print(self.__dict__)
            return self.__passwd
    
        def login(self):
            return self.__get_pwd()
    
    alec = Person('alec','123456')
    print(alec.__dict__)                # 查看类内部的所有属性,然后可以强制调用私有属性
    pwd =alec.login()
    print(pwd)
    
  • 应用场景:

    • 隐藏起一个属性,不想让类的外部调用
    • 保护这个属性,不想让属性随意被改变
    • 保护这个属性不被子类继承
posted @ 2020-05-18 18:28  薛定谔的猫儿  阅读(86)  评论(0编辑  收藏  举报