python学习day33笔记

单继承下的属性查找

问题1

class Foo:
    def f1(self):
        print('Foo1')
        
    def f2(self):
        ptint('Foo2')
        self.f1()
        
class Bar(Foo):
    def f1(self):
        print('Bar1')
        
obj = Bar()
obj.f2()

逻辑顺序:Bar中没有f2,从父类找到f2后父类要调用self的f1,此时self是obj这个对象,obj对应的是Bar(),所以从Bar内找f2
# 碰到这种问题先查出self是谁

问题2

class Foo:
    def __f1(self):
        print('Foo1')
        
    def f2(self):
        ptint('Foo2')
        self.__f1()
        
class Bar(Foo):
    def __f1(self):
        print('Bar1')
        
obj = Bar()
obj.f2()

逻辑顺序:Bar中没有f2,从父类找到f2后要调用__f1,隐藏属性对只外,此时运行的是 class.Foo 类,所以f2内的__f1变形后应该是_Foo__f1,所以从Foo内找__f1

多继承下的属性查找

菱形结构

假设A有多个父类,父类也有各自的父类,而最终的父类是object,就会组成一个◇菱形,这种继承关系称之为菱形结构

菱形结构分为两种查找方式:
1.深度优先(经典类)
2.广度优先(新式类)

深度优先(经典类)

class A(B,C,D):
    pass

class B(E):
    pass

class C(F):
    pass

class D:
    pass

查找顺序是A->B->E->object->C->F->D
先按照顺序沿着一条线查到底,再从下一条线开始查找

广度优先(新式类)

class A(B,C,D):
    pass

class B(E):
    pass

class C(F):
    pass

class D:
    pass

查找顺序是A->B->E->C->F->D->object
先每条线都找到除最顶级object以外的底,最后再找到object

非菱形继承

假设A有多个父类,父类也有各自的父类,而他们没有最终汇总的一个类,属性查找没有顺序要求,所以不用分成广度优先和深度优先

super

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:
            self.courses = []
        # super(Student,self).__init__(name,age,gender)  
        # python2需要将自己的类名和self写上
        super().__init__(name,age,gender)
        # python3
        
    def choose_course(self,course):
        self.courses.append(course)
        print(f'{self.name}选课成功{self.courses}')
        
class Teacher(People):
    def __init__(self,name,age,gender,level):
        self.level = level
        super().__init__(name,age,gender)

        
stu1 = Student('egon',18,'male')

MRO列表

通过 print(类名.__mro__) 或者 print(类名.mro()) 可以查找到类的继承关系
所有的父类mro列表会遵循如下三条准则:
1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类

class A:
    def test(self):
        print('A---->test')
        super().aaa()
class B:
    def test(self):
        print('B---->test')

    def aaa(self):
        print('B---->aaa')

class C(A,B):
    def aaa(self):
        print('C----->aaa')
        
c = C()
c.test()  # A---->test  B---->aaa  
# 逻辑顺序:C内没有test,所以从上级找,第一个上级是A,A里恰好有test,所以运行A.test,A.test内的代码super().aaa(),意思是从上级找aaa()对象,这里的self是c,也就是C(),从C()的上级找aaa(),从B找到了B---->aaa

多态与多态性

多态

一种事物的多种状态称为多态
例:水->冰,水,水蒸气
	动物->人,猪,狗
    
class Animal():
    def speak(self):
        pass
    def run(self):
        pass
    
class People(Animal):
    pass

class Dog(Animal):
    pass

class Pig(Animal):
    pass

# people,dog,pig都是动物的多种形态,他们都是动物
obj = People()
obj1 = Dog()
obj2 = Pig()

# 继承解决冗余问题,是一把双刃剑,用不好反而更加麻烦
# 多态类中的继承不是为了让子类遗传父类的属性和方法,是用来给子类定制标准的

import abc  # abstract -> 抽象

# 该类已经成为抽象类了
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def speak(self):
        pass
    def run(self):
        pass
    
class People(Animal):
    def jiao():  # 把动物里的speak改成jiao
        pass

class Dog(Animal):
    def speak:
        pass
    pass

class Pig(Animal):
    def speak:
        pass
    pass

obj = People()  # 报错
# 只要把speak定为抽象方法,如果将Animal定为父类,父类不实现,子类必须实现speak不然报错

多态性

多态性:多态带来的特性,在不用考虑对象数据类型的情况下直接调用对象的方法

# python崇尚鸭子类型:即看起来像鸭子,用起来像鸭子,那你就是鸭子
def animal(animal):
    return animal.speak()
# 只要你使用animal,那默认传递的值就是动物
animal(obj)

类似于:
def len(item):
    return item.__len__()
len('abc')

# 再举例 在linux中一切皆文件
class People():
    def read(self):
        pass
    def write(self):
        pass

class Student():
    def read(self):
        pass
    def write(self):
        pass
# 他们都有读和写的功能,虽然没有继承,但只要它长得像,叫的像,那他就是鸭子(文件)

组合

解决类与类之间的冗余问题:
1.继承:满足 什么是什么的关系->人是动物
2.组合:满足 什么有什么的关系->动物里有人

组合:一个对象拥有一个属性,该属性是另外一个对象

class People():
    school = 'SH'
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender

class Course():
    def __init__(self,course_name,course_period,course_price):
        self.course_name = course_name
        self.course_period = course_period
        self.course_price = course_price
        
class Student(People):
    def __init__(self,name,age,gender,course=None):
        if course is None:
            self.courses = []
        super.__init__(name,age,gender)
        
    def choose_course(self,course):
        self.courses.append(course)
        print(f'{self.name}选课成功{self.courses}')
        
class Teacher(People):
    def __init__(self,name,age,gender,level):
        self.level = level
        super.__init__(name,age,gender)
    
    def score(self,stu_obj,num):
        stu_obj.num = num
        print(f'{self.name}老师给{stu_obj.name}打了{num}分')
        
stu1 = Student('egon',18,'male')
python = Course('python','6month',20000)
stu1.courses.append(python)
# 这里没有用继承关系继承Course,因为继承需要满足什么是什么的关系,明显课程不是学生也不是老师,所以直接存在Course类里,需要的时候造一个对象然后再变成另一个对象的属性,没有冗余
posted @ 2021-07-14 21:28  麋鹿的麋  阅读(42)  评论(0)    收藏  举报