Python面向对象编程-02

本知识点参考廖雪峰的Python课程 [https://www.liaoxuefeng.com]

感谢北京图灵知非的免费课程 [http://www.tulingxueyuan.com/]

2018/6/26 星期二 11:15:57

继承和多态

  • 继承就是一个类可以获得另外一个类中的成员属性和成员方法

    • 作用: 减少代码,增加代码的复用功能, 同时可以设置类与类直接的关系
  • 继承与被继承的概念:
    • 被继承的类叫父类,也叫基类,也叫超类
    • 用于继承的类,叫子类,也叫派生类
    • 继承与被继承一定存在一个 is-a 关系
  • 继承的语法:
        class Animal(object):
            def run(self):
            print("Animal is runnung...")
        # Animal 继承于object,第一个类都继承于object,不管你写不写`object`
        class Dog(Animal):
            pass
        # Dog继承于Animal
        class Cat(Animal):
            pass
        # Cat继承于Animal
  • 对于Dog来说,Animal就是它的父类,对于Animal来说,Dog就是它的子类
  • 继承的好处就在于子类获得了父类的全部功能。Dog也有了AnimalRun() 方法
    >>> dog = Dog()
    # 子类一旦继承父类,则可以使用父类中除私有成员外的所有内容
    >>> dog.run
    Animal is runnung...
  • 我们对上面代码再次进行改进,给DogCat添加一些方法
        class Dog(Animal):
            def run(self):
                print(‘Dog is running...‘)
        class Cat(Animal):
            def run(self):
                print(‘Cat is running...‘)
  • 运行:
        >>> dog = Dog()
        >>> cat = Cat()
        >>> dog.run()
        >>> cat.run()
        Dog is running...
        Cat is running...
  • 我们可以看到这里,子类和父类都存在run方法时,子类的run()覆盖了父类的run().在代码运行的时候总会调用子类的run().这样我们就获得了继承的另外一个好处,多态。

    多态

  • 要理解什么是多态,我们首先要对数据类型再作一点说明。当我们定义一个class的时候,我们实际上就定义了一种数据类型。我们定义的数据类型和Python自带的数据类型,比如str、list、dict没什么两样:
        a = list() # a是list类型
        b = Animal() # b是Animal类型
        c = Dog() # c是Dog类型
  • 判断一个变量是否是某个类型可以用isinstance()判断:
         >>> isinstance(a, list)
         True
         >>> isinstance(b, Animal)
         True
         >>> isinstance(c, Dog)
         True
  • 看来abc都对于着list、Animal、Dog这三种类型
  • 但是:
        >>> isinstance(c,Animal)
        True
  • 看来c不仅仅是Dog,c还是Animal

    不过仔细想想,这是有道理的,因为Dog是从Animal继承下来的,当我们创建了一个Dog的实例c时,我们认为c的数据类型是Dog没错,但c同时也是Animal也没错,Dog本来就是Animal的一种!

  • 所以,在继承关系中,如果一个实例的数据类型是某个子类,那它的数据类型也可以被看做是父类。但是,反过来就不行:
        >>> b = Animal()
        >>> isinstance(b, Dog)
        False
  • 要理解多态的好处,我们编写一个函数
        def run_twice(animal):
            animal.run()
            animal.run()
  • 当我们传入Animal的实例时,run_twice()就打印出:
        >>> def run_twice(Animal()):
        Animal is running..
        Animal is running..
  • 当我们传入Dog的实例时,run_twice()就打印出:
        >>> def run_twice(Dog()):
        Dog is running..
        Dog is running..
  • 当我们传入Cat的实例时,run_twice()就打印出:
        >>> def run_twice(Cat()):
        Cat is running..
        Cat is running..
  • 如果我们再定义一个Tortoise类型,也从Animal派生:
        class Tortoise(Animal):
            def run(self):
                print(‘Tortoise is running slowly...‘)  
  • 当我们调用run_twice()时,传入Tortoise的实例:
        >>> run_twice(Tortoise())
        Tortoise is running slowly...
        Tortoise is running slowly...
  • 对于一个变量,我们只需要知道它是Animal类型,无需确切地知道它的子类型,就可以放心地调用run()方法,而具体调用的run()方法是作用在Animal、Dog、Cat还是Tortoise对象上,由运行时该对象的确切类型决定,这就是多态真正的威力:调用方只管调用,不管细节,而当我们新增一种Animal的子类时,只要确保run()方法编写正确,不用管原来的代码是如何调用的。这就是著名的“开闭”原则:
    • 对扩展开放:允许新增Animal子类;
    • 对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。


添加:

  • super()
  • 子类如果想扩充父类的方法,可以在定义新方法的同时访问父类成员来进行代码重用,可以使用 [父类名.父类成员] 的格式来调用父类成员,也可以使用super().父类成员的格式来调用。
        class Animal(object):
            def run(self):
            print("Animal is runnung...")
    
        class Dog(Animal):
            def run(self):
                print(‘Dog is running...‘)
        class Cat(Animal):
            def run(self):
                super().run()
                print(‘Cat is running...‘)
  • 继承变量函数的查找顺序问题
    • 优先查找自己的变量
    • 没有则查找父类
    • 构造函数如果本类中没有定义,则自动查找调用父类构造函数
    • 如果本类有定义,则不在继续向上查找
  • 构造函数
    • 是一类特殊的函数,在类进行实例化之前进行调用
    • 如果定义了构造函数,则实例化时使用构造函数,不查找父类构造函数
    • 如果没定义,则自动查找父类构造函数
    • 如果子类没定义,父类的构造函数带参数,则构造对象时的参数应该按父类参数构造

多继承于重继承

  • 继承面向对象编程的一个重要方式,通过继承,子类就可以扩展父类的功能
  • 如果我们把我们能想到的动物进行分类
    • Dog - 狗狗;
    • Bat - 蝙蝠;
    • Parrot - 鹦鹉;
    • Ostrich - 鸵鸟
  • 我们能飞的,能跑的,能游的,哺乳动物等分类,就太麻烦了,类的数量会指数级增长
  • 我们正确的做法是采用多重继承,首先主要层次任然安装哺乳动物,和鸟类分:
    class Animal(object):
        pass
    
    # 大类:
    class Mammal(Animal):
        pass
    
    class Bird(Animal):
        pass
    
    # 各种动物:
    class Dog(Mammal):
        pass
    
    class Bat(Mammal):
        pass
    
    class Parrot(Bird):
        pass
    
    class Ostrich(Bird):
        pass
  • 然后,我们在给动物加上Runnable和Flyable的功能,只需要先定义好Runnable和Flyable的类:
    class Runnable(object):
        def run(self):
            print(‘Running...‘)
    
    class Flyable(object):
        def fly(self):
            print(‘Flying...‘)

    -对于需要Runnable功能的动物,就多继承一个Runnable,例如Dog:

    class Dog(Mammal, Runnable):
        pass
  • 对于需要Flyable功能的动物,就多继承一个Flyable,例如Bat:
    class Bat(Mammal, Flyable):
        pass

    通过多重继承,一个子类就可以同时获得多个父类的所有功能。


  • Mixin
  • Mixin设计模式
  • 我们使用多继承语法来实现Minxin
  • 使用Mixin实现多继承的时候非常小心
    • 首先他必须表示某一单一功能,而不是某个物品
    • 职责必须单一,如果由多个功能,则写多个Mixin
    • Mixin不能依赖于子类的实现
    • 子类及时没有继承这个Mixin类, 也能照样工作,只是缺少了某个功能
  • 优点
    • 使用Mixin可以在不对类进行任何修改的情况下,扩充功能
    • 可以方便的组织和维护不同功能组件的划分
    • 可以根据需要任意调整功能类的组合
    • 可以避免创建很多新的类,导致类的继承混乱

原文地址:https://www.cnblogs.com/yangaoteng666/p/9228177.html

时间: 2024-10-29 00:07:17

Python面向对象编程-02的相关文章

Python面向对象编程-封装

1引言 你点击了桌面上的Chrome图标,一个浏览器窗口出现了,输入网址就可以在Internet世界愉快玩耍.这一切是怎么实现的呢?Chromium这个多进程的程序是如何启动各个进程的呢?浏览器主进程(界面进程)启动了哪些线程?如何启动的呢?这些问题一直萦绕在心头,一起来看看源代码吧.本文主要针对Chromium for Mac的源代码,其它操作系统大同小异. 2背景知识 浏览器作为一个应用程序,是以进程的形式运行在操作系统上的.首先,Chromium是一个多进程的应用程序,我们需要了解Chro

(转)Python 面向对象编程(一)

Python 面向对象编程(一) 虽然Python是解释性语言,但是它是面向对象的,能够进行对象编程.下面就来了解一下如何在Python中进行对象编程. 一.如何定义一个类 在进行python面向对象编程之前,先来了解几个术语:类,类对象,实例对象,属性,函数和方法. 类是对现实世界中一些事物的封装,定义一个类可以采用下面的方式来定义: class className: block 注意类名后面有个冒号,在block块里面就可以定义属性和方法了.当一个类定义完之后,就产生了一个类对象.类对象支持

python 面向对象编程(一)

一.如何定义一个类 在进行python面向对象编程之前,先来了解几个术语:类,类对象,实例对象,属性,函数和方法. 类是对现实世界中一些事物的封装,定义一个类可以采用下面的方式来定义: class className: block 注意类名后面有个冒号,在block块里面就可以定义属性和方法了.当一个类定义完之后,就产生了一个类对象.类对象支持两种操作:引用和实例化.引用操作是通过类对象去调用类中的属性或者方法,而实例化是产生出一个类对象的实例,称作实例对象.比如定义了一个people类: cl

Python面向对象编程总结(上)

在我学习python之前一直认为python是脚本型语言,不能用面相对象的方法进行编程,当我学习了python之后我发现我错了,python不但支持面相对象而且使用的人还挺多的.我从接触编程开始就是学习的Java语言,所以面相对象编程的思想在我的脑海里根深蒂固,让我一下从面向对象编程转换到面向过程编程还有一些不适应呢,所以我就来总结一下python面向对象编程的方法和过程.我将按照面向对象的构成要素来分析,依次为类和实例.属性.方法.封装.继承.多态,如果有什么问题还请大家积极指出,我所用的版本

python面向对象编程(OOP)

python作为一种解释性语言,其主要的编程方式就是面向对象,而且python的框架django也是主要面向对象的编程. 类(class)和对象(object) 类(class)是用来描述具有相同属性(attribute)和方法(method)对象的集合.对象(object)是类(class)的实例.比如学生都有名字和分数,他们有着共同的属性.这时我们就可以设计一个学生类,用来记录学生的名字和分数,并自定义打印出来. 属性(attribute):类里面用于描述所有对象共同特征的变量或数据.比如此

Python面向对象编程指南(高清版)PDF

Python面向对象编程指南(高清版)PDF百度网盘链接:https://pan.baidu.com/s/1SbD4gum4yGcUruH9icTPCQ 提取码:fzk5 复制这段内容后打开百度网盘手机App,操作更方便哦内容简介 · · · · · · Python是一种面向对象.解释型的程序设计语言,它已经被成功应用于科学计算.数据分析以及游戏开发等诸多领域.本书深入介绍Python语言的面向对象特性,全书分3个部分共18章.第1部分讲述用特殊方法实现Python风格的类,分别介绍了init

python面向对象编程进阶

python面向对象编程进阶 一.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 1 class Foo(object): 2 pass 3 4 obj = Foo() 5 6 isinstance(obj, Foo) issubclass(sub, super)检查sub类是否是 super 类的派生类 1 class Foo(object): 2 pass 3 4 class B

Python网络编程02/基于TCP协议的socket简单的通信

目录 Python网络编程02/基于TCP协议的socket简单的通信 1.昨日内容回顾 2.socket 2.1 socket套接字 2.2 基于TCP协议的socket简单通信 Python网络编程02/基于TCP协议的socket简单的通信 1.昨日内容回顾 1.单播:单独联系某一个人 2.广播:给所有人发送消息(群发) 3.比特流:bit就是0101跟水流一样的源源不断的发送01010101 4.以太网协议:将数据进行分组:一组称之为一帧,数据报 head|data head:18字节:

python并发编程02/多进程

目录 python并发编程02/多进程 1.进程创建的两种方式 1.1开启进程的第一种方式 1.2开启进程的第二种方式 1.3简单应用 2.进程pid 2.1命令行获取所有的进程的pid tasklist 2.2代码级别如何获取一个进程的pid 2.3获取父进程(主进程)的pid 3.验证进程之间的空间隔离 4.进程对象join方法 5.进程对象其他属性 6.守护进程 python并发编程02/多进程 1.进程创建的两种方式 1.1开启进程的第一种方式 from multiProcessing