多态

对于函数中的变量,我们只需要知道它这个变量是什么类,无需确切地知道它的子类型,就可以放心地调用类的方法,而具体调用的这个方法是作用在父类对象还是子类对象上,由运行时该对象的确切类型决定,这就是多态真正的威力

>>>class Animal:          #定义一个父类
  def run(self):
    print('animal is running...')
>>>class Dog(Animal): #继承于Animal类
  def run(self):
    print('Dog is running...')
>>>class Cat(Animal): #继承于Animal类
  def run(self):
    print('Cat is running...')
>>>def run_twice(animal): #此处新建一个函数,且此函数接受一个animal类型的变量
  animal.run()
  animal.run()

当我们传入Animal的实例时,run_twice()就打印出:

>>>run_twice(Animal())
Animal is running...
Animal is running...

当我们传入Dog的实例时,run_twice()就打印出:

>>>run_twice(Dog())
Dog is running...
Dog is running...

当我们传入Cat的实例时,run_twice()就打印出:

>>>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...

由上可以发现,多态的好处就是,当我们需要传入Dog、Cat、Tortoise……时,我们只需要接收Animal类型就可以了。然后,按照Animal类型进行操作即可,由于Animal类型有run()方法,因此,传入的任意类型,只要是Animal类或者子类,就会自动调用实际类型的run()方法,这就是多态的意思。

调用方只管调用,不管细节,而当我们新增一种父类的子类时,只要确保类的方法编写正确,不用管原来的代码是如何调用的。这个就是著名的“开闭”原则:

对扩展开放:允许新增Animal子类;

对修改封闭:不需要修改依赖Animal类型的run_twice()等函数

由于python是动态语言,所以run_twice()中不一定必须传入Animal类型,只要保证传入的对象有一个run()方法就可以了,上述结论就是动态语言的鸭子类型,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。

>>>class Demi:
  def run(self):
    print('demi is a girl')
>>>run_twice(Demi())
demi is a girl
demi is a girl

组合

组合指的是,在一个类中以另外一个类的实例对象作为数据属性

作用是可以将两个本来不相关的类联系起来,一般是两个类之间有显著的不同

>>>class Turtle:
  def __init__(self,x):
    self.num = x
>>>class Fish:
  def __init__(self,x):
    self.num = x
>>>class Pool:
  def __init__(self,x,y):
    self.turtle = Turtle(x)
    self.fish = Fish(y)
  def number(self):
    print("水池里总共%s只乌龟,共%s条鱼" % (self.turtle.num,self.fish.num))

有纵向关系用继承,无纵向关系用组合

简单的说,组合用于“有一个”的场景中,继承用于“是一个”的场景中。例如,水池里有一个乌龟,天上有一个鸟,这些适合使用组合。青瓜是瓜,女人是人,鲨鱼是鱼,这些就应该使用继承

Python笔记(二十)_多态、组合的更多相关文章

  1. Python笔记(二十九)_模块

    模块 在Python中,一个.py文件就是一个模块 if __name__ == '__main__':所有模块都有一个 __name__ 属性,__name__ 的值取决于如何应用模块 run当前文 ...

  2. Python笔记(二十六)_魔法方法_属性的魔法方法

    属性的魔法方法 __getattribute__(self,name):当该类的属性被访问时,自动触发,是最先被触发的属性方法 __setattr__(self,name,value):当一个属性被设 ...

  3. Python笔记(二十四)_魔法方法_运算符的魔法方法

    算数运算方法 .反运算方法 以对象A+对象B为例,都是将A作为self值,而B作为other值传入__add__(self,other)方法: 当用户输入A+B,就会调用重写的add方法: >& ...

  4. Python笔记(二十二)_魔法方法_基本魔法方法

    __init__(self[,...]) __init__和__new__组成python的构造器,但__init__更多的是负责初始化操作,相当于一个项目中的配置文件,__new__才是真正的构造函 ...

  5. Python笔记(二十八)_魔法方法_迭代器

    迭代器用于遍历容器中的数据,但它不是容器,它是一个实现了__next__方法的对象 与迭代器相关的内置函数: iter(): 将一个对象转换成一个迭代器 next(): 访问迭代器中的下一个变量,直到 ...

  6. Python笔记(二十五)_魔法方法_描述符

    描述符的属性方法 __get__(self, instance, owner): 用于访问属性,返回属性的值 __set__(self, instance, value): 用于给属性赋值时,返回属性 ...

  7. Python爬虫(二十)_动态爬取影评信息

    本案例介绍从JavaScript中采集加载的数据.更多内容请参考:Python学习指南 #-*- coding:utf-8 -*- import requests import re import t ...

  8. [b0035] python 归纳 (二十)_多进程数据共享和同步_共享内存Value & Array

    1. Code # -*- coding: utf-8 -*- """ 多进程 数据共享 共享变量 Value,Array 逻辑: 2个进程,对同一份数据,一个做加法,一 ...

  9. Python笔记(二十七)_魔法方法_容器

    定制容器 容器类型的协议: 定制不可变容器,只需要定义__len__()和__getitem__()方法 定制可变容器,需要定义__len__().__getitem__().__setitem__( ...

随机推荐

  1. Acwing‘803. 区间合并

    (https://www.acwing.com/problem/content/805/) 给定 nn 个区间 [li,ri][li,ri],要求合并所有有交集的区间. 注意如果在端点处相交,也算有交 ...

  2. Redis主从同步、哨兵、集群

    什么是主从同步(复制) 主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器.前者称为主节点(master),后者称为从节点(slave),数据的复制是单向的,只能由主节点到从节点 ...

  3. SpringMVC Controller单例和多例(转)

    首先上测试代码 import org.springframework.context.annotation.Scope; import org.springframework.stereotype.C ...

  4. asp.net中的<% %>,<%= %>,<%# %><%$ %>的使用

    原文:https://www.cnblogs.com/Hackerman/p/3857630.html 首先我们来看一下<% %>的使用 在aspx的页面中只能使用服务器控件和一般的控件, ...

  5. Angular.js 使用$http的response得到的phone属性为undefined

    这是个坑~ 先说解决方案:把response打印出来找你的属性 记录一下,经验不足,有些东西想当然了,所有错误出现都应该一步步去排查!!!切记想当然的自以为. 源码: js $scope.phone= ...

  6. 5.canvas

    1.canvas:固定语句:定义画布/设置绘图环境为2d. 2.canvas样式:lineWidth线宽/strokeStyle绘制样式. 3.canvas绘制矩形: Context.moveTo(x ...

  7. ASE Alpha Sprint - backend scrum 8

    本次scrum于2019.11.13再sky garden进行,持续30分钟. 参与人: Zhikai Chen, Jia Ning, Hao Wang 请假: Xin Kang, Lihao Ran ...

  8. 读取FTP上的excel文件,并写入数据库

    今天遇到一些问题,需要从ftp上读取一些excel文件,并需要将excel中的数据写入到数据库,这样就可以通过管理页面查看这些数据. 我将相关工作分为三步,1.从ftp上读取相关文件,并将excel文 ...

  9. 一、Core的布局页、起始页及错误页

    一.布局页面: 使用布局页相当于一个母版页,可以将各个页面公用部分,如上方标题区.左侧导航菜单区.下方版权声明及状态显示区以及通用的js及css引用等,集中放到布局页管理,具体功能页面只需关注自己独有 ...

  10. shell 搜索指定目录下所有 jar 文件生成csv文件

    虽说比较简单,但希望分享给大家.按需求改成想找的:例如txt,xls 等. 脚本名 扫描的路径 文件名 testFind.sh /  testFind.txt (如果未配置环境变量  ./testFi ...