Day17 python基础---面向对象三大特性---继承

时间:2022-02-24 18:40:07

一,继承和抽象概念

  1.抽象:即抽取类似或者比较像的部分。抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类。

     抽象分成两个层次:

    1)将奥巴马和梅西这俩对象比较像的部分抽取成类;

    2)将人,猪,狗这三个类比较像的部分抽取成父类。

        2.继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。

     

二,单继承

       1.语法:父类,子类

          父类/超类/基类

          子类/派生类

  2.继承与重用

           父类所有的属性和方法都可以被子类使用

class Animal:  #父类/超类/基类 
    def __init__(self,name,kind,food,language):
        self.name = name
        self.kind = kind
        self.food = food
        self.language = language

    def yell(self):
        print('%s叫'%self.language)
    def eat(self):
        print('%s吃%s'%(self.name,self.food))
    def drink(self):
        print('%s喝'%self.name)

class Cat(Animal):  #子类/派生类 
    def catch(self):
        print('%s抓老鼠'%self.name)

class Dog(Animal):  #子类/派生类 
    def look_after_house(self):
        print('%s看家'%self.name)

# 继承与重用 -  父类中所有的属性和方法都可以被子类使用了
阿猫 = Cat('阿猫','橘猫','猫粮','喵喵')
阿狗 = Dog('阿狗','二哈','狗粮','汪汪')
print(阿猫.name)
阿猫.drink()
阿猫.eat()
阿猫.catch()
阿猫.yell()

  3.继承与派生

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

              1.父类有的子类没有:子类对象直接调用,就会直接执行父类的方法

              2.父类有的子类也有:子类对象调用,直接执行子类中的方法,若在子类中使用父类的属性和方法:父类名、super()去调用

class Cat(Animal):   #Animal的派生类
    def __init__(self,name,kind,food,language,eye_color):
        self.eye_color = eye_color   #派生属性
        Animal.__init__(self,name,kind,food,language)
        #super().__init__(name,kind,food,language)
    def catch(self):    #派生方法
        print('%s抓老鼠'%self.name)
    def eat(self):    # 不仅执行了父类中的基础功能,还完成了特殊的功能
        Animal.eat(self)
        #super().eat()
        self.weight = 10
# 当子类当中有要被调用的方法的时候,子类的对象会直接选择子类中的方法、变量,父类中的方法不会被自动执行
# 如果我们既想要执行子类的方法,也想要执行父类的方法,那么需要在子类的方法中调用父类的方法:
#   父类名.方法名(self,...)
#   super().方法名(...)
#   帮助我们在子类中调用父类中的同名方法
# 面向对象特性之继承--面试题
#当self去调用某个方法的时候,不要看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() ################## class Foo: Country = 'China' def func(self): print(self.Country) class Son(Foo): Country = 'English' def func(self): # 走这个方法 print(self.Country) s = Son() s.func() #################### class Foo: Country = 'China' def func(self): # 走这个方法 print(self.Country) class Son(Foo): Country = 'English' s = Son() s.func() # English ######################### class Foo: Country = 'China' def func(self): print(self.Country) class Son(Foo):pass s = Son() s.func() # 'China'

  4.规范的编程模式:抽象类

        抽象类的概念:

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

         2.工作中,有的公司源码有使用抽象类开发的规则,在多人开发,复杂的需求,后期的扩展的场景中,使用抽象类来帮助我们完成规范

# 抽象类语法
        # from abc import ABCMeta,abstractmethod
        # 在这个类创建的时候指定 metaclass = ABCMeta
        # 在你希望子类实现的方法上加上一个 @abstractmethod装饰器

#抽象类的使用
        # 继承这个类
        # 必须实现这个类(子类创建同名的方法)中被@abstractmethod装饰器装饰的方法
from  abc import ABCMeta,abstractmethod

class Payment(metaclass=ABCMeta):   # 模板的功能
    @abstractmethod       # abstractmethod是一个装饰器,放在函数/类的上一行
    def pay(self):pass   #该抽象类的子类,都必须实现父类的方法,否则报错

class Alipay(Payment):
    def pay(self,money):
        print('使用支付宝支付了%d'%money)

class wechatpay(Payment):
    def pay(self,money):
        print('使用支付宝支付了%d'%money)

def pay(obj,money):#构造函数存入对象和参数,自动调用类的方法
    obj.pay(money)

#TypeError: Can't instantiate abstract class Payment with abstract methods pay
#p = Payment()  #抽象类实例化会报错
a = Alipay()
w = wechatpay()
pay(a,100)
pay(w,150)
#所有的对象的type都是创造这个对象类
class A:pass
obj = A()
type(obj) is A
#所有没有指定metaclass的类的type都是type
#如果指定了metaclass,那么这个类的type就是指定的metaclass的值
#类也是被创造出来的,type是创造类的机制,即元类是创造类的机制
#例:补全func:
#     - dir方法能够得到当前文件中的所有成员
#     - 获取handler中名字叫Base的成员
#     - 检查其他成员是否是Base类的子类(不包含Base),如果是则创建对象并添加到objs列表中。


class Base(object):pass

class F1(Base):pass

class F2(Base):pass

class F3(F2):pass

class F4(Base):pass

class F5(object):pass

class F6(F5):pass

import sys
def func():
    name_lst = dir(sys.modules[__name__])
    obj_list = []
    for name in name_lst:
        name_addr = getattr(sys.modules[__name__],name)
        print(type(name_addr))
        if type(name_addr) is type and issubclass(name_addr,Base) and name_addr is not Base:
            obj_list.append(name_addr())
    return obj_list
ret = func()
print(ret)

 

 

 

 

三,多继承

       1.不是所有的语言都支持多继承,例,jave,c#

        2.由于python支持多继承,所以python没有接口类

        3.其他不支持多继承的语言的接口类,相当于只是继承了一个规范,继承接口类规范的类必须实现接口类的方法

#python的多继承语法
class Parent1:pass
class Parent2:pass
class Son(Parent1,Parent2):pass
print(Son.__bases__)   #__bases__查看所有父类,__base__只查看从左到右继承的第一个子类
class Animal:
    def __init__(self,name):
        self.name = name

class FlyAnimal(Animal):
    def fly(self):
        print('%s在飞'%self.name)

class WalkAnimal(Animal):
    def walk(self):
        print('%s在走路'%self.name)

class SwimAnimal(Animal):
    def swim(self):
        print('%s在游泳'%self.name)

class Tiger(SwimAnimal,WalkAnimal):
    pass

class Swan(SwimAnimal,WalkAnimal,FlyAnimal):
    pass

class Parrot(FlyAnimal,WalkAnimal):
    def talk(self):
        print('%s说话了'%self.name)

swan = Swan('天鹅')
swan.fly()
swan.walk()

  4.新式类和经典类

         #新式类:

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

         #继承object

         #mro方法

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

          #经典类:

             #python2.x

        #不主动继承object

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

      #不提供mro方法和super()

# python 2.7
# 经典类 和 新式类 并存
# class Student:pass # 经典类
# class Student(object):pass

# 继承了object的类就是新式类
# 在py3中所有的类都是新式类
# 在py2中既有新式类又有经典类

# 多继承的顺序 在新式类和经典类之间的区别
class A:
    def func(self):
        print('A')

class B(A):
    # pass
    def func(self):
        print('B')

class C(A):
    # pass
    def func(self):
        print('C')

class D(B,C):
    # pass
    def func(self):
        print('D')
print(D.mro())
d = D()
d.func()