多态

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

>>>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. Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式)

    Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式) 题外话,这是我第40篇随笔,纪念一下.<( ̄︶ ̄)↗[GO!] 题意 是说有棵树,每个节点上 ...

  2. Python自学第二天学习之《元组与字典》

    一.  元组:tuple类型,元组一级元素 不能修改 不能增加 不能删除,是有序的. 格式 :tu=(1,2,3,4,5,6) 1.类型转换: #字符串转换成元组 b=“123” c=tuple(b) ...

  3. HDU-1181 变形课(多种方式,好题)

      首先想到的是并查集,然后WA...原因在这,我第一次敲的是Find(1) == Find(12)来作为可以成功的条件,实际上这样是不行的,比方说 bell 和 mail实际上是不满足条件的,可以理 ...

  4. Keyboarding (bfs+预处理+判重优化)

    # #10030. 「一本通 1.4 练习 2」Keyboarding [题目描述] 给定一个 $r$ 行 $c$ 列的在电视上的"虚拟键盘",通过「上,下,左,右,选择」共 $5 ...

  5. asp.net 几种传值方法的分析

    本文转自:http://www.cnblogs.com/shengtianlong/archive/2010/08/11/1797608.html ASP.NET页面传值方法的优缺点及适用范围 1. ...

  6. Android客户端与Python服务器端的简单通信

    最近在做一个APP,需要与服务器通信,一点一点的尝试,记录一下. 本文使用了OkHttp和Flask框架. 参考博文:https://ai-exception.com/2018/06/13/%E4%B ...

  7. 手写符合Promise/A+规范的Promise

    const PENDING = "pending"; const RESOLVED = "resolved"; const REJECTED = "r ...

  8. netcore项目使用swagger开发

    首先我创建一个netcore项目,我使用的工具是vs2019 这里需要注意的是,看情况选择是否开启身份验证,一般是没有需求的,这里因为我是测试使用所以需要取消勾兑为https配置,并且我没有启用doc ...

  9. 2019-3-6-WPF-使用-SharpDX

    title author date CreateTime categories WPF 使用 SharpDX lindexi 2019-03-06 16:52:37 +0800 2018-4-20 9 ...

  10. mysql +keeplive+drbd高可用架构(MHA基于监听端口VIP的高可用)

    1MySQL+DRBD+keepalived高可用架构 DRBD(DistributedReplicatedBlockDevice)是一个基于块设备级别在远程服务器直接同步和镜像数据的开源软件,类似于 ...