Python笔记(二十)_多态、组合
多态
对于函数中的变量,我们只需要知道它这个变量是什么类,无需确切地知道它的子类型,就可以放心地调用类的方法,而具体调用的这个方法是作用在父类对象还是子类对象上,由运行时该对象的确切类型决定,这就是多态真正的威力
>>>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笔记(二十)_多态、组合的更多相关文章
- Python笔记(二十九)_模块
模块 在Python中,一个.py文件就是一个模块 if __name__ == '__main__':所有模块都有一个 __name__ 属性,__name__ 的值取决于如何应用模块 run当前文 ...
- Python笔记(二十六)_魔法方法_属性的魔法方法
属性的魔法方法 __getattribute__(self,name):当该类的属性被访问时,自动触发,是最先被触发的属性方法 __setattr__(self,name,value):当一个属性被设 ...
- Python笔记(二十四)_魔法方法_运算符的魔法方法
算数运算方法 .反运算方法 以对象A+对象B为例,都是将A作为self值,而B作为other值传入__add__(self,other)方法: 当用户输入A+B,就会调用重写的add方法: >& ...
- Python笔记(二十二)_魔法方法_基本魔法方法
__init__(self[,...]) __init__和__new__组成python的构造器,但__init__更多的是负责初始化操作,相当于一个项目中的配置文件,__new__才是真正的构造函 ...
- Python笔记(二十八)_魔法方法_迭代器
迭代器用于遍历容器中的数据,但它不是容器,它是一个实现了__next__方法的对象 与迭代器相关的内置函数: iter(): 将一个对象转换成一个迭代器 next(): 访问迭代器中的下一个变量,直到 ...
- Python笔记(二十五)_魔法方法_描述符
描述符的属性方法 __get__(self, instance, owner): 用于访问属性,返回属性的值 __set__(self, instance, value): 用于给属性赋值时,返回属性 ...
- Python爬虫(二十)_动态爬取影评信息
本案例介绍从JavaScript中采集加载的数据.更多内容请参考:Python学习指南 #-*- coding:utf-8 -*- import requests import re import t ...
- [b0035] python 归纳 (二十)_多进程数据共享和同步_共享内存Value & Array
1. Code # -*- coding: utf-8 -*- """ 多进程 数据共享 共享变量 Value,Array 逻辑: 2个进程,对同一份数据,一个做加法,一 ...
- Python笔记(二十七)_魔法方法_容器
定制容器 容器类型的协议: 定制不可变容器,只需要定义__len__()和__getitem__()方法 定制可变容器,需要定义__len__().__getitem__().__setitem__( ...
随机推荐
- 到底如何设置 Java 线程池的大小?
来源:ifeve.com/how-to-calculate-threadpool-size/ 在我们日常业务开发过程中,或多或少都会用到并发的功能.那么在用到并发功能的过程中,就肯定会碰到下面这个问题 ...
- Spring-Boot 整合Dubbo 解决@Reference 注解为null情况
首先检查一下你的spring boot版本是多少? 如果是2.X 不用看了,spring boot 2.x 必定会出现这个问题, 改为 1.5.9 或其他1.x版本,目前生产环境建议使用1.x版本. ...
- BlockingQueue 阻塞队列(生产/消费者队列)
1:BlockingQueue的继承关系 java.util.concurrent 包里的 BlockingQueue是一个接口, 继承Queue接口,Queue接口继承 Collection Blo ...
- Python 内置函数raw_input()和input()用法和区别
我们知道python接受输入的raw_input()和input() ,在python3 输入raw_input() 去掉乐,只要用input() 输入,input 可以接收一个Python表达式作为 ...
- docker相关知识
DevOps 是一个完整的面向IT运维的工作流,以 IT 自动化以及持续集成(CI).持续部署(CD)为基础,来优化程式开发.测试.系统运维等所有环节.突出重视软件开发人员和运维人员的沟通合作,通过自 ...
- node+mysql+express实现登录/注册/修改密码/删除用户 接口
实现用户的注册.登录.修改密码.删除用户操作 用到的数据库:nodecms:表:user 目录结构: db目录下存放数据库操作语句: userSQL.js 用户有关的操作语句 router目录 接口路 ...
- PgSQL · 特性分析 · PG主备流复制机制
原文地址:http://mysql.taobao.org/monthly/2015/10/04/ PostgreSQL在9.0之后引入了主备流复制机制,通过流复制,备库不断的从主库同步相应的数据,并在 ...
- 搭建Keepalived+LNMP架构web动态博客 实现高可用与负载均衡
环境准备: 192.168.193.80 node1 192.168.193.81 node2 关闭防火墙 [root@node1 ~]# systemctl stop firewalld #两台都 ...
- md5sum 计算和校验文件的md5值
1. 命令功能 md5算法一般用于检查文件完整性, 2. 语法格式 md5sum [option] [file] 参数 参数说明 -b 以二进制模式读入文件 -t 以文本模式读入文件 -c 用来从 ...
- 手写split功能
def split_new(stringstr, charstr): """ :param stringstr: 要分割的串 :param charst ...