day30 继承和鸭子类型

今日内容概要

  • 继承(面向对象中得核心)

    • 单继承 多继承

  • 单继承下的属性查找

  • 多继承下的属性查找

  • super和mro的使用

  • 多态和鸭子类型

  • 组合

  • mixins机制(理论、规范)

今日内容详细

继承(面向对象中得核心)
面向对象的三大特征:封装、继承、多态
1. 什么是继承?
      继承就是一种新建类的方式, 新建出来的类我们称为是'子类或者叫派生类',被继承的类我们称为是'父类或者是基类'
      当然出来的类子类可以遗传父类的所有属性
   
2. 为什么要用继承?
      类解决了什么问题: 对象与对象之间的代码冗余问题
       继承解决了什么问题:类与类之间的代码冗余问题
​
3. 怎么使用继承?
     经典类:没有继承object类的子子孙孙类都是经典类
      新式类:继承了object类的子子孙孙类都是新式类
     """
        再有在Python2中才区分经典类和新式类,如果是Python3的版本,所有的类都是新式类,也就是说在Python3中默认的类都是继承了object类,在Python3中没有了经典类和新式类的说法了.
     """
    
 class Parent1:
    pass
​
​
class Parent2(object):
    pass
​
​
"""Sub1类继承了Parent1的类,Sub1就称为是子类,Parent1类就称为是父类或者叫基类"""
# 单继承:一个类只继承了一个类,一个类继承了两个或者两个以上的类就是多继承了
class Sub1(Parent1):
    pass
​
​
# 多继承的类: Sub2就是子类,Parent1和Parent2都是父类
class Sub2(Parent1, Parent2):
    pass
​
print(Sub1.__bases__) # (<class '__main__.Parent1'>,)
print(Sub2.__bases__) # (<class '__main__.Parent1'>, <class '__main__.Parent2'>)
​
"""继承的实际案例"""
​
​
class People():
    school = 'SH'
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
​
class Student(People):
    def __init__(self, name, age, gender, course=None):
        if course is None:
            course = []
        """子类里面一定再次调用父类的__init__方法"""
        People.__init__(self, name, age, gender) # 指名道姓的调用方法
        self.course = course
​
    def choose_course(self):
        print('%s 选课成功, %s' % (self.name, self.course))
​
​
stu = Student('ly', 20, 'male')
print(stu.school)  # SH 属性的查找
print(stu.name)
print(stu.age)
print(stu.gender)
​
​
class Teacher(People):
    def __init__(self, name, age, gender, level):
        People.__init__(self, name, age, gender)
        self.level = level
​
    def score(self, stu_name):
        print('%s 得了%s分' % (stu_name, 10))
​
tea = Teacher('kevin', 19, 'female')
print(tea.name)
print(tea.age)
print(tea.gender)

单继承下的属性查找

class A():
    def f2(self):
        pass
​
class Foo(A):
    def __f1(self):  # _Foo__f1
        print('from Foo.f1')
​
    # def f2(self):
    #     print('from Foo.f2')
    #     self.__f1() # _Foo__f1
​
​
class Bar(Foo):
    def __f1(self): # _Bar__f1
        print('from Bar.f1') # from Bar.f1
"""单继承下的属性查找:先从对象自己名称空间中查找,然后去产生这个对象的类中查找,最后去继承的父类中查找."""
obj = Bar()
obj.f2()  #

多继承下的属性查找

多继承下分菱形查找和非菱形查找
​
菱形查找分 经典类 和 新式类
经典类:按照深度优先的查找顺序
新式类:按照广度优先查找
class G: # 在python2中,未继承object的类及其子类,都是经典类
    def test(self):
        print('from G')
​
class E(G):
    def test(self):
        print('from E')
​
class F(G):
    def test(self):
        print('from F')
​
class B(E):
    def test(self):
        print('from B')
​
class C(F):
    def test(self):
        print('from C')
​
class D(G):
    def test(self):
        print('from D')
​
class A(B,C,D):
    # def test(self):
    #     print('from A')
    pass
​
obj = A()
obj.test() # 如上图,查找顺序为:obj->A->B->E->G->C->F->D->object
# 可依次注释上述类中的方法test来进行验证,注意请在python2.x中进行测试
​
class G(object):
    def test(self):
        print('from G')
​
class E(G):
    def test(self):
        print('from E')
​
class F(G):
    def test(self):
        print('from F')
​
class B(E):
    def test(self):
        print('from B')
​
class C(F):
    def test(self):
        print('from C')
​
class D(G):
    def test(self):
        print('from D')
​
class A(B,C,D):
    # def test(self):
    #     print('from A')
    pass
​
obj = A()
obj.test() # 如上图,查找顺序为:obj->A->B->E->C->F->D->G->object
# 可依次注释上述类中的方法test来进行验证
​
"""python3中都是新式类,都是广度优先查询"""

super和mro的使用

class A:
    def test(self):
        super().test()
​
​
class B:
    def test(self):
        print('from B')
​
​
class C(A, B):
    pass
​
"""mro列表是通过一个C3算法得出来的,我们无需明白底层原理,只需要知道每个类的mro列表到底是什么,然后按照这个列表去查找就行"""
# 在打印mro列表的时候,一定是从起始类开始
# c = C()
# c.test()
# print(C.mro()) # [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
# print(C.__mro__)
​
"""mro列表,每个类都有自己的mro列表,怎么查看类的mro列表"""
a = A()
# a.test()
print(A.mro()) # (<class '__main__.A'>, <class 'object'>)
print(A.__mro__)

多态和鸭子类型

多态它是面向对象的三大特征
​
什么是多态?
    同一种事物的多种形态
    
举例:
    水:气态水、液态水、固态水
     动物:人、狗、猪、等都是动物的一种形态
"""之所以说人、狗、猪是动物,是因为他们都具备动物的特征,speak功能"""
import abc # abstract class 抽象类   具体的Specific
​
class Animal(metaclass=abc.ABCMeta): # 把animal类变成了抽象类
    """父类中得方法不是为了实现逻辑的,实现功能的,而是单纯的为了限制子类的行为"""
    @abc.abstractmethod # 把抽象类中得方法变成抽象方法, 它不实现具体的功能,就是单纯的为了限制子类中的方法
    def speak(self):
        pass
    @abc.abstractmethod
    def jiao(self):
        pass
​
​
"""抽象类和普通类有什么区别? 抽象类只能够被继承、不能够被实例化"""
​
# Animal() # Can't instantiate abstract class Animal with abstract methods speak
​
"""怎么限制子类People类必须有speak功能? 我们可以在父类中来限制子类的行为,其实就是限制子类中必须有某些方法"""
​
​
"""Python崇尚的是鸭子类型"""
​
"""鸭子类型就是更多的关注的是对象的行为,而不是对象的类型"""
​
class People(Animal):
    def speak(self):pass
        # print('from People.speak')
    def jiao(self):
        pass
​
class Dog(Animal):
    def speak(self):
        pass
​
​
class Pig(Animal):
    def speak(self):
        pass
​
"""多态带来的特性:在不考虑对象类型的情况下,直接调用对象的方法或者属性"""
def animal(obj):
    return obj.speak()
​
animal(obj)
animal(obj1)
animal(obj2)
​
"""面试题:请举出Python中使用多态的例子:len"""
​
len('hello')
len([1,2,3,4])
len((1,2,3,4))
​
​
def len(obj):
    return obj.__len__
len('helloworld')
len([1,2,3,4])
len((1,2,3,4))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值