python 面向对象之继承、多态与鸭子类型

发布时间:2022-06-28 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了python 面向对象之继承、多态与鸭子类型脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

目录
  • 1.面向对象的三大特征
  • 2.类的继承
  • 3.单继承下的属性查找
  • 4.多继承下的属性查找
  • 5.关键字super()和mro()
  • 6.多态与多态性与鸭子类型

1.面向对象的三大特征

# 面向对象的三大特征:封装、继承、多态

2.类的继承

1.什么是继承?
	继承是新建类的一种方式,新建的类被称为子类或者派生类,被继承的类被称为父类或者基类。
2.为什么要用继承
	子类可以使用父类的属性和方法。
    类解决了对象与对象之间代码冗余的问题
    继承解决了类与类之间代码冗余的问题。
3.继承的分类:
	经典类:没有继承object类的子子孙孙类的都属于经典类
    新式类:继承了object类的子子孙孙类的都属于新式类。
    
    # 在python2中才有经典类和新式类之分,在python3中都是新式类。

4.查看父类
print(子类名.__bases__)
    
5.类的继承
# 以学生选课系统为例:
# 定义一个公共的类,把学生类和老师类里面 一样的东西拿出来
class People():
    school = '老男孩'
    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 = []
        People.__init__(self, name, age, gender)
        self.course = course

    def choose_course(self, course):
        self.course.append(course)
        print('%s选课成功%s' % (self.name, course))
# 调用类产生对象
stu1 = Student('qql', 18, 'female', 'python')
print(stu1.name)
# 老师类
class Teacher():
    def __init__(self, name, age, gender, level):
        People.__init__(self, name, age, gender)
        self.level = level
    def score(self, stu_obj, score):
        stu_obj.score = score
        print('%s给%s打了%s分' % (self.name, stu_obj.name, score))
t1 = Teacher('jason', 20, 'male', 10)
print(t1.name)
t1.score(stu1, 80)

python 面向对象之继承、多态与鸭子类型

python 面向对象之继承、多态与鸭子类型

3.单继承下的属性查找

有了继承关系后,对象在查找属性的时候,会先在自己的__dict__里面查找,如果找不到,就去产生自己的子类里面找,如果再找不到,就会去父类里面找。

# 举例
class Foo:
    def f1(self):
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')
        self.f1()


class Bar(Foo):
    def f1(self):
        print('Bar.f1')


obj = Bar()  # 没有传入参数的生成的对象就是一个空字典  {}
obj.f2()  # 要确认到底self是谁


# 练习 父类如果不想让子类覆盖自己的方法,可以采用隐藏方法设置成自己私有的

class Foo:
    def __f1(self):  # _Foo__f1()  # 隐藏属性对外不对内
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')
        self.__f1()  # _Foo__f1()  指名道姓的拿


class Bar(Foo):
    def __f1(self):  # _Bar__f1()
        print('Bar.f1')


obj = Bar()  # 没有传入参数的生成的对象就是一个空字典  {}
obj.f2()  # 要确认self到底是谁


python 面向对象之继承、多态与鸭子类型

python 面向对象之继承、多态与鸭子类型

4.多继承下的属性查找

1.经典类(菱形问题)(了解)--深度优先
如果继承多个类,从左往右查找。左边分支到最深后,到左二分支...

# 经典类:深度优先
class A(object):
    def test(self):
        print('from A')
class B(A):
    def test(self):
        print('from B')
class C(A):
    def test(self):
        print('from C')
class D(B, C):
    pass

obj = D()
obj.test()

2.新式类(分支不相交)--广度优先
在父类从左右到查找,先不查到最深的那个
查到最右边的父类再到最深那个
# 新式类:广度优先
class A(object):
    def test(self):
        print('from A')
class B(A):

    pass
class C(A):

    pass
class D(B):

    pass
class E(C):

    pass
class F(D, E):

    pass
f1 = F()
f1.test()


python 面向对象之继承、多态与鸭子类型

python 面向对象之继承、多态与鸭子类型

5.关键字super()和mro()

调用super()会得到一个特殊的对象,该对象专门用来引用父类的属性,并且严格按照C3线性(mro)的顺序向后查找。使用时会自动传入self参数,不能在写,否则参数多了。

Python 2 中: super(自己的类名, self).__init__( 参数1, 参数2 ···) 完整写法。
Python 3 中:  super().__init__( 参数1, 参数2 ···) 简写。

class People():
    school = 'SH'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


class Teacher(People):
    def __init__(self, name, age, gender, level):
        self.level = level
        super().__init__(name, age, gender)  # super的使用:按照C3线性查找


print(Teacher.__mro__)  # C3线性 : (<class '__main__.Teacher'>, <class '__main__.People'>, <class 'object'>)
t1 = Teacher('qql', 20, 'male', 10)


# 练习
# mro列表练习1
class A():
    def test(self):
        print('from A.test')
        super().test()

class B:
    def test(self):
        print('from B')

class C(A, B):
    pass

c = C()
c.test()
print(C.__mro__)  # 查看C3线性


# mro列表练习2
class B:
    def test(self):
        print('B---->test')
    def xixi(self):
        print('B---->aaa')

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

class C(A, B):
    def aaa(self):
        print('C----->aaa')
c = C()
c.test()
print(C.mro())  # 查看C的C3线性继承



python 面向对象之继承、多态与鸭子类型

python 面向对象之继承、多态与鸭子类型

python 面向对象之继承、多态与鸭子类型

6.多态与多态性与鸭子类型

1.什么是多态
	多态即事物的多种状态
    
2. # 抽象类只能被继承,不能被实例化
	导入abc模块,在父类体代码中方法的顶上紧贴着使用@abc.abstractmethod,会把该方法变成抽象方法,抽象方法体中不能写代码,只能写pass;子类体代码中必须要有一样的方法名来实现,否则就会报错,这种方法在python中不推荐使用。

import abc
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod  # 紧贴着的下面那个方法变成抽象方法,也就是说子类必须有该方法实现
    def speak(self):  
        pass  # 抽象方法体不能写代码,只能写pass
    @abc.abstractmethod  # 紧贴着的下面那个方法变成抽象方法,也就是说子类必须有该方法实现
    def login(self):  
        pass  # 抽象方法体不能写代码,只能写pass
# a1 = Animal()  实例化会报错
class People(Animal):
    def speak(self):
        print('嗷嗷嗷')
    def login(self):
        pass
class Pig(Animal):
    def speak(self):
        print('哼哼哼')
    def login(self):
        pass
class Dog(Animal):
    def speak(self):
        print('汪汪汪')

obj = People()
obj.speak()

3. # 多态推荐用法
	定义一个有参函数,传入对象返回值 对象.方法名()

# 例子
# 多态练习
class Pig():
    def speak(self):
        print('哼哼哼')
class Dog():
    def speak(self):
        print('汪汪汪')
class Txt():
    def speak(self):
        print('Txt')
# 定义一个有参函数,传入对象返回对象.方法名()
def animal(animal):
    return animal.speak()
# 调用类产生对象
obj1 = Pig()
obj2 = Dog()
obj3 = Txt()
# 多态带来的特性:在不用考虑对象数据类型的情况下,可以直接调用对应的函数
animal(obj1)  # obj1.speak()
animal(obj2)  # obj2.speak()
animal(obj3)  # obj3.speak()


4. # 父类限制子类的行为
	父类有该方法,用raise主动报错限制子类必须有该方法,如果子类没有的话,找到父类那里就会主动报错。
class Animal():
    def speak(self):
        # 主动报错:如果子类里面没有该方法又想用父类的方法,就会报错
        raise Exception("必须实现speak方法")
class Pig(Animal):
    def speak(self):
        print('哼哼哼')
class Dog(Animal):
    school = '老男孩'
    print(school)
class Txt(Animal):
    def speak(self):
        print('Txt')

obj1 = Dog()
obj1.speak()

5.鸭子类型(duck teying)
	不依赖于继承,只需要制造出外观和行为相同对象,同样可以实现不考虑对象类型而使用对象。这正是Python崇尚的“鸭子类型”(duck typing):“如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子”。比起继承的方式,鸭子类型在某种程度上实现了程序的松耦合度。
    
#二者看起来都像文件,因而就可以当文件一样去用,然而它们并没有直接的关系
class Txt: #Txt类有两个与文件类型同名的方法,即read和write
    def read(self):
        pass
    def write(self):
        pass

class Disk: #Disk类也有两个与文件类型同名的方法:read和write
    def read(self):
        pass
    def write(self):
        pass

python 面向对象之继承、多态与鸭子类型

python 面向对象之继承、多态与鸭子类型

python 面向对象之继承、多态与鸭子类型

脚本宝典总结

以上是脚本宝典为你收集整理的python 面向对象之继承、多态与鸭子类型全部内容,希望文章能够帮你解决python 面向对象之继承、多态与鸭子类型所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: