Python教程

python之面向对象进阶

本文主要是介绍python之面向对象进阶,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

    • 1.类的继承
      • 1.1 什么是继承
      • 1.2 为什么要用继承
      • 1.3 如何使用继承
    • 2. 类的分类
      • 2.1 新式类
      • 2.2 经典类
    • 3. 继承与抽象
    • 4. 继承后对象查找属性的顺序
      • 4.1 单继承查找顺序
      • 4.2 多继承查找循序
        • 4.2.1 非菱形继承问题
        • 4.2.2 菱形继承下查找顺序
    • 5. 派生与mro列表
      • 5.1 派生
        • 5.1.1 类调用
        • 5.1.2 super()方法
      • 5.2 MRO列表
    • 6. 多态与多态性
      • 6.1. 多态

1.类的继承

1.1 什么是继承

  • 继承就是新建类的一种方式, 新建的类我们称为子类或者叫做派生类, 被继承的类我们称为父类或者基类

  • 继承的特性是: 子类会遗传父类的属性

1.2 为什么要用继承

  • 类解决了对象与对象之间代码冗余问题

  • 继承解决了类与类之间代码冗余问题

1.3 如何使用继承

  • python中支持多继承(即一个类能够同时继承多个父类)
class Parent1:
    pass

class Parent2:
    pass

class Sub1(Parent1, Parent2):
    pass
  • 可以使用双下bases(bases)方法获取对象继承的类
print(Sub1.__bases__)

# (<class '__main__.Parent1'>, <class '__main__.Parent2'>)
  • 在python3 中如果一个类没有继承任何类, 则默认继承object类
  • 在python2 中如果一个类没有继承任何类, 不会继承object类
    在这里插入图片描述

2. 类的分类

2.1 新式类

  • 继承了object的类以及该类的子类,都是新式类
  • python3中所有的类都是新式类

2.2 经典类

  • 没有继承object的类以及该类的子类, 都是经典类
  • 只有python2中才有经典类

3. 继承与抽象

  • 继承是描述子类与父类之间的关系, 是一种什么是什么的关系。要找出这种关系,必须先抽象再继承, 抽象即抽取类似或者说比较像的部分。

  • 抽象分为两个层次:

    1. 将奥巴马和梅西这俩对象比较像的部分抽取成类
    2. 将人,猪,狗这三个类比较像的部分抽取成父类

    img

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

    89-类的继承-继承图.png
    在这里插入图片描述

4. 继承后对象查找属性的顺序

4.1 单继承查找顺序

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()  

'''
顺序: 对象自己(obj)-> 对象的类(Bar)-> 父类(Foo) -> 父类
'''

在这里插入图片描述

4.2 多继承查找循序

4.2.1 非菱形继承问题

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

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

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


obj = Bar()  # {}
obj.f2()  
'''
父类顺序,按照从左往右循序查找,找完一条没有再重另外一条查找
顺序: 对象自己(obj)-> 对象的类(Bar)-> 父类(Foo) -> 父类(Aoo) -> 父类
'''

在这里插入图片描述

4.2.2 菱形继承下查找顺序

1. 什么是菱形继承
	菱形继承是指一个类同时继承多个父类,父类或父类的父类最终都继承同一个类,例如
# 新式类:按照广度优先查询(如下图1)

# 经典类:按照深度优先查询(如下图2)

class A(object):
    def test(self):
        print('from A')


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

class C(A):
    def test(self):
        print('from C')
    pass


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

class E(C):
    def test(self):
        print('from E')
    pass


class F(D, E):
    def test(self):
        print('from F')
    pass

经典类的深度优先查找

新式类的广度优先查找
在这里插入图片描述

5. 派生与mro列表

5.1 派生

  • 派生:子类中新定义的属性的这个过程叫做派生,并且需要记住子类在使用派生的属性时始终以自己的为准

5.1.1 类调用

指名道姓访问某一个类的函数: 该方式与继承无关
class People:
    """由于学生和老师都是人,因此人都有姓名、年龄、性别"""
    school = 'oldboy'

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


class Student(OldboyPeople):
    """由于学生类没有独自的__init__()方法,因此不需要声明继承父类的__init__()方法,会自动继承"""

    def choose_course(self):
        print('%s is choosing course' % self.name)


class Teacher(OldboyPeople):
    """由于老师类有独自的__init__()方法,因此需要声明继承父类的__init__()"""

    def __init__(self, name, age, gender, level):
        People.__init__(self, name, age, gender)
        self.level = level  # 派生

    def score(self, stu_obj, num):
        print('%s is scoring' % self.name)
        stu_obj.score = num


stu1 = Student('tom', 18, 'male')
tea1 = Teacher('tony', 18, 'male', 10)

在这里插入图片描述

5.1.2 super()方法

  • 严格以来继承属性查找关系
  • super()会得到一个特殊的对象,该对象就是专门用来访问父类中的属性的(按照继承的关系)
  • super().init(不用为self传值)
  • super的完整用法是super(自己的类名,self),在python2中需要写完整,而python3中可以简写为super()
单继承使用super() 可以直接使用
class People:
    """由于学生和老师都是人,因此人都有姓名、年龄、性别"""
    school = 'oldboy'

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


class Student(OldboyPeople):
    """由于学生类没有独自的__init__()方法,因此不需要声明继承父类的__init__()方法,会自动继承"""

    def choose_course(self):
        print('%s is choosing course' % self.name)


class Teacher(OldboyPeople):
    """由于老师类有独自的__init__()方法,因此需要声明继承父类的__init__()"""

    def __init__(self, name, age, gender, level):
        # People.__init__(self, name, age, gender)
        # super(People, self).__init__(self, name, age, gender)
        super().__init__(self, name, age, gender)
        self.level = level  # 派生

    def score(self, stu_obj, num):
        print('%s is scoring' % self.name)
        stu_obj.score = num

5.2 MRO列表

  • mro列表就是在多继承情况下,通过c3算法得出的属性查找顺序
  • 使用方式: 类名.mro()
在多继承情况下,可以通过mro来查看查找顺序,super()是依赖于继承的,并且即使没有直接继承关系,super()仍然会按照MRO继续往后查找

在这里插入图片描述

6. 多态与多态性

6.1. 多态

  • 多态指的是一类事物有多种形态,比如动物有多种形态: 猫、狗、猪
class Animal: #同一类事物:动物
    def talk(self):
        pass
class Cat(Animal): #动物的形态之一:猫
    def talk(self):
        print('喵喵喵')
class Dog(Animal): #动物的形态之二:狗
    def talk(self):
        print('汪汪汪')
class Pig(Animal): #动物的形态之三:猪
    def talk(self):
        print('哼哼哼')

#实例化得到三个对象
cat=Cat()
dog=Dog()
pig=Pig()
  • 多态性的本质在于不同 的类中定义有相同的方法名,这样我们就可以不考虑类而统一用一种方式去使用对象
def Talk(animal):
    animal.talk()
  • python中一切皆对象,本身就支持多态性
# 我们可以在不考虑三者类型的情况下直接使用统计三个对象的长度
s.__len__()
l.__len__()
t.__len__()

# Python内置了一个统一的接口
len(s)
len(l)
len(t)
  • 可以通过在父类引入抽象类的概念来硬性限制子类必须有某些方法名
import abc
# 通过父类来限制子类
# 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法
    def talk(self): # 抽象方法中无需实现具体的功能,也不能添加功能,只能pass
        pass

class Cat(Animal): # 但凡继承Animal的子类都必须遵循Animal规定的标准
    def talk(self):
        pass

cat=Cat() # 若子类中没有一个名为talk的方法则会抛出异常TypeError,无法实例化

鸭子类型定义: 如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子

个人想法: 只要有相同的方法和属性,那就可以规划为同一个类
在这里插入图片描述

这篇关于python之面向对象进阶的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!