多态

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

>>>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. [2019杭电多校第二场][hdu6601]Keen On Everything But Triangle

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6601 题意是说用给定区间内的数字组成周长最大的三角形. 大致做法就是求区间第1大,第2大和第3大然后判 ...

  2. make: *** 没有指明目标并且找不到 makefile

    make: *** 没有指明目标并且找不到 makefile. 停止. make: *** 没有规则可以创建目标“install”. 停止.   不是没有makefile文件,而是你没有安装gcc编译 ...

  3. django 中 slice 和 truncatewords 不同用法???

    django中取一段字符串中的前 N 个字符,可以用 slice和truncatewords ,但是两者是有区别的. django的 模板过滤器 truncatewords ,取这个模板变量的前 N ...

  4. PC端实现浏览器点击分享到QQ好友,空间,微信,微博等

    网上现在比较流行的是JIaThis,但是测试的时候,不能分享给QQ好友,一直卡在输入验证码,以下代码亲测有效,可直接使用 <%@ page language="java" c ...

  5. Docker实战部署应用——MySQL5.7

    MySQL 部署 拉取MySQL镜像 拉取命令: docker pull mysql:5.7 查看镜像 docker images 创建 MySQL 容器 docker run -id --name= ...

  6. CentOS7安装mysql8.0编译报错集合

    以下都是我安装mysql8.0遇到的一些报错和解决方法 1.does not appear to contain CMakeLists.txt. 原因:mysql下载的源码包不对 解决方法:下载正确的 ...

  7. QT生成可执行的EXE程序

    [转载] Qt 官方开发环境使用的动态链接库方式,在发布生成的exe程序时,需要复制一大堆 dll,如果自己去复制dll,很可能丢三落四,导致exe在别的电脑里无法正常运行.因此 Qt 官方开发环境里 ...

  8. 修改图片尺寸网站https://www.yasuotu.com/

    修改图片尺寸网站https://www.yasuotu.com/

  9. 转 Java中wait和sleep方法的区别

    1.两者的区别 这两个方法来自不同的类分别是Thread和Object 最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法(锁代码块和方法锁). wait ...

  10. @ResponseBody和@RestController

    Spring 关于ResponseBody注解的作用 responseBody一般是作用在方法上的,加上该注解表示该方法的返回结果直接写到Http response Body中,常用在ajax异步请求 ...