Python_015(面向对象(接口类,抽象类,多态,封装)
一.抽象类与接口类
1.抽象类:抽象即类似或者说比较像的部分,继承描述的是父类与子类的一种关系,要找出这种关系,必须先抽象再继承;
a:抽象分成两个层次:
1)由对象->类:将两个有相似地方的对象抽取成类;
2)由类->父类:将两个有相似地方的类抽取成父类;
:抽象最主要的作用就是划分类别(可以隔离关注点,降低复杂度)
2.为什么要有抽象类
与Java一样,Python也有抽象类的概念,需要借助模块实现,它是一个特殊的类,特殊之处在于只能被继承,不能被实例化;
类是从一些对象中抽取相同的内容而来的,那如果类中有相似的地方,就引出了抽象类概念,
所以从实现的角度来看,抽象类与普通类的不同之处在于:抽象类只能有抽象方法(没有实现功能),这个类不能被实例化,只能被继承,且子类必须实现抽象方法;
#用代码来表示一下接口类和抽象类:
- #版本一
- class Alipay:
- def __init__(self,money):
- self.money = money
- def pay(self):
- print('阿里支付了%s元!' % self.money)
- class Jdpay:
- def __init__(self,money):
- self.money = money
- def pay(self):
- print('京东支付了%s元!' % self.money)
- p1 = Alipay(1000)
- p1.pay() #这里是Alipay.pay()
- p2 = Jdpay(1000)
- p2.pay() #这里是Jdpay.pay()
- #输出结果:
- 阿里支付了1000元!
- 京东支付了1000元!
#虽然你调用pay方法格式没有错,但是不合理,工作中如果有人接着你的程序写一个微信支付,它写的格式和你的可能就不一样,不能体现归一化的设计理念;
2)所以引出第二版(接口的概念)
a:接口提取了一群类共同的函数,可以把接口当做一个函数的集合,然后让子类去实现接口中的函数
这么做的意义在于归一化,归一化就是只要基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,
从用法上来说都一样;
归一化的好处在于:
1. 归一化让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。
2. 归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合
代码展示:
- #版本二
- class Alipay:
- def __init__(self,money):
- self.money = money
- def pay(self):
- print('阿里支付了%s元!' % self.money)
- class Jdpay:
- def __init__(self,money):
- self.money = money
- def pay(self):
- print('京东支付了%s元!' % self.money)
- def pay(obj): #接口函数(约定俗成,内行程序员大家都看的懂)
- obj.pay()
- p1 = Alipay(1000)
- pay(p1)
- p2 = Jdpay(1000)
- pay(p2)
- #输出结果:
- 阿里支付了1000元!
- 京东支付了1000元!
**这种做法相对于有素质的程序员行,但是万一来个野生程序员,还按版本一的方式写,就又乱套了;
所以引出第三种写法:抽象类(类似于接口)起规范化作用:
- class Pay(metaclass=ABCMeta):
- all_type = 'alex'
- @abstractmethod #每一个子类中都要有这个方法,定义格式
- def pay(self):pass #规范一个方法上面加一句@abstractmethod
- class Alipay(Pay):
- def __init__(self,money):
- self.money = money
- def pay(self):
- print('阿里支付了%s元!' % self.money)
- class Jdpay(Pay):
- def __init__(self,money):
- self.money = money
- def pay(self):
- print('京东支付了%s元!' % self.money)
- class Wxpay(Pay):
- def __init__(self,money):
- self.money = money
- def wupay(self): #这里没有pay方法,再实例化对象时会报错
- pass
- p1 = Wxpay(200)
- #输出结果:
- TypeError: Can't instantiate abstract class Wxpay with abstract methods pay
二.多态
1.多态概念:多态就是一个对象有多种状态,例如文件有可执行文件和文本文件;
2.多态性:这是指在不考虑实例类型的情况下使用实例
- 就比如:老师,下课铃响了(),学生,下课铃响了(),老师执行的是下班操作,学生执行的是方向操作,
虽然二者消息一样,但是执行的效果不同;
3.多态的好处:a:增加了程序的灵活性 b:增加了程序的可扩展性
4.鸭子类型:Python崇尚鸭子类型,即"如果看起来像,叫声而且走路像鸭子,那么它就是鸭子",其实Python中没有多态的概念,因为它处处都是多态,不用考虑数据类型,传入函数,封装到对象都可以.
举例1:你只要像鸭子,我就可以用鸭子的方法或属性对你使用;
利用标准库中定义的各种‘与文件类似’的对象,尽管这些对象的工作方式像文件,但他们没有继承内置文件对象的方法
- #二者都像鸭子,二者看起来都像文件,因而就可以当文件一样去用
- class TxtFile:
- def read(self):
- pass
- def write(self):
- pass
- class DiskFile:
- def read(self):
- pass
- def write(self):
- pass
例2:其实大家一直在享受着多态性带来的好处,比如Python的序列类型有多种形态:字符串,列表,元组,多态性体现如下:
- #str,list,tuple都是序列类型
- s=str('hello')
- l=list([1,2,3])
- t=tuple((4,5,6))
- #我们可以在不考虑三者类型的前提下使用s,l,t
- s.__len__()
- l.__len__()
- t.__len__()
- len(s)
- len(l)
- len(t)
三.封装
1. a:广义的封装:
实例化一个对象,给对象空间封装一些属性;
b:狭义的封装:私有制,私有静态字段,私有方法,私有对象属性;
格式为__变量名或则__方法名
2.私有封装的特点
a:实例化的对象不能在外访问私有静态字段;
b:类名在外不能访问静态字段; 所以对于私有静态字段,类的外部和派生类都不能访问;
c:对于私有静态字段来说,只有在本类内部方法或属性中可以访问
3.讲解在定义私有封装属性是Python内部机制
在Python中用双下划线开头的方式将属性隐藏了起来(设置成私有的)
- #其实这仅仅这是一种变形操作且仅仅只在类定义阶段发生变形
- #类中所有双下划线开头的名称如__x都会在类定义时自动变形成:_类名__x的形式:
- class A:
- __N=0 #类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N
- def __init__(self):
- self.__X=10 #变形为self._A__X
- def __foo(self): #变形为_A__foo
- print('from A')
- def bar(self):
- self.__foo() #只有在类内部才可以通过__foo的形式访问到.
- #A._A__N是可以访问到的,
- #这种,在外部是无法通过__x这个名字访问到。
所以在函数外部,你若想要访问函数私有变量或方法,只需要在前面加上_类名__方法名()即可;
4.封装的意义
1).封装数据:将数据隐藏起来这不是目的,隐藏起来后对外提供接口时,我们可以直接在接口上对该数据操作做出限制,以此完成对数据属性操作的严格控制;
- class Teacher:
- def __init__(self,name,age):
- # self.__name=name
- # self.__age=age
- self.set_info(name,age)
- def tell_info(self):
- print('姓名:%s,年龄:%s' %(self.__name,self.__age))
- def set_info(self,name,age):
- if not isinstance(name,str):
- raise TypeError('姓名必须是字符串类型')
- if not isinstance(age,int):
- raise TypeError('年龄必须是整型')
- self.__name=name
- self.__age=age
- t=Teacher('egon',18)
- t.tell_info()
- t.set_info('egon',19)
- t.tell_info()
2).封装方法:不能直接调用我的方法,你只能看到一个最终的接口
封装方法举例:
1. 你的身体没有一处不体现着封装的概念:你的身体把膀胱尿道等等这些尿的功能隐藏了起来,然后为你提供一个尿的接口就可以了(接口就是你的。。。,),你总不能把膀胱挂在身体外面,上厕所的时候就跟别人炫耀:hi,man,你瞅我的膀胱,看看我是怎么尿的。
2. 电视机本身是一个黑盒子,隐藏了所有细节,但是一定会对外提供了一堆按钮,这些按钮也正是接口的概念,所以说,封装并不是单纯意义的隐藏!!!
3. 快门就是傻瓜相机为傻瓜们提供的方法,该方法将内部复杂的照相功能都隐藏起来了
提示:在编程语言里,对外提供的接口(接口可理解为了一个入口),可以是函数,称为接口函数,这与接口的概念还不一样,接口代表一组接口函数的集合体。
- #取款是功能,而这个功能有很多功能组成:插卡、密码认证、输入金额、打印账单、取钱
- #对使用者来说,只需要知道取款这个功能即可,其余功能我们都可以隐藏起来,很明显这么做
- #隔离了复杂度,同时也提升了安全性
- class ATM:
- def __card(self):
- print('插卡')
- def __auth(self):
- print('用户认证')
- def __input(self):
- print('输入取款金额')
- def __print_bill(self):
- print('打印账单')
- def __take_money(self):
- print('取款')
- def withdraw(self):
- self.__card()
- self.__auth()
- self.__input()
- self.__print_bill()
- self.__take_money()
- a=ATM()
- a.withdraw()
Python_015(面向对象(接口类,抽象类,多态,封装)的更多相关文章
- python开发面向对象基础:接口类&抽象类&多态&钻石继承
一,接口类 继承有两种用途: 一:继承基类的方法,并且做出自己的改变或者扩展(代码重用) 二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实 ...
- day27 多态 多继承 接口类 抽象类
简单来说:多态就是指一个相同的方法名在不同的对象调用的时候实现一样或者不一样的方法实例1: 动物类有个方法 "嚎叫" 狗类也有个方法 "嚎叫" 猫类继承了动物类 ...
- python笔记5 接口类抽象类 封装 反射 设计模式 模块 :random随机数 josn shelve持久化存储
接口类抽象类 接口类:接口类就是制定一个规则,让其他人按照我的规则去写程序. #!/usr/bin/env python from abc import ABCMeta,abstractmethod ...
- Python进阶-XVII 非python的接口类、多态、python自己的封装
1.python模拟java中的接口类 python中是没有接口类的概念的,因为它支持多继承,但是java不能,所以就提出一个接口类的概念 java : 面向对象编程 设计模式 —— 接口 接口类 : ...
- 日历类和日期类转换 并发修改异常 泛型的好处 *各种排序 成员和局部变量 接口和抽象类 多态 new对象内存中的变化
day07 ==和equals的区别? ==用于比较两个数值 或者地址值是否相同. equals 用于比较两个对象的内容是否相同 String,StringBuffer.StringBuilde ...
- python's twenty-first day for me 抽象类和接口类以及多态
归一化设计: 不管是哪一个类的对象,都调用同一个函数去完成相似的功能. class Alipay: def pay(self,money): print('使用支付宝支付了%s' % money) c ...
- php中普通类 接口类 抽象类 浅谈
一.普通类 1.关键词:class 类名,继承关键字extends 2.继承:只能实现单继承, 3.多态:子类继承可以实现多种功能 4.封装:类有权限机制,私有的只能自己用,受保护的可以被继承,子类 ...
- python学习之老男孩python全栈第九期_day025知识点总结——接口类、抽象类、多态、封装
一. 接口类 java:面向对象编程 设计模式 -- 接口类 接口类:python原生不支持 抽象类:python 原生支持的 from abc import abstractclassmethod, ...
- day 25-1 接口类、抽象类、多态
# 接口类:python 原生不支持# 抽象类:python 原生支持的 接口类 首先我们来看一个支付接口的简单例子 from abc import abstractmethod,ABCMeta #我 ...
随机推荐
- springcloud(一)
Spring Cloud是什么鬼? Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中的配置管理.服务发现.断路器.智能路由.微代理.控制总线. ...
- express接受ajax的发送post请求
两种常用的方式: $.ajax({ type: "POST", url: '/everdayPost', // data: JSON.parse({cont:data}),注意: ...
- 取(2堆)石子游戏 HDU 2177 博弈论
取(2堆)石子游戏 HDU 2177 博弈论 题意 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中 ...
- ubuntu 新建root用户
1. sudo passwd :设置root用户密码 2. 切换用户 方式一:su 方式二: su root 3. 新增普通用户
- 【PDF】手写字与识别字重叠
[PDF]手写字与识别字重叠 前言 同学平时上课用iPad记笔记,考试之前导出为PDF发给我后,我用PDF打开,发现可以直接Ctrl+F搜索一些词语.一直不知道是怎么做到的,毕竟里面的字都是手写的,不 ...
- RouteReuseStrategy angular路由复用策略详解,深度刨析路由复用策略
关于前端路由复用策略网上的文章很多,大多是讲如何实现tab标签切换历史数据,至于如何复用的原理讲的都比较朦胧,代码样例也很难适用各种各样的路由配置,比如懒加载模式下多级嵌套路由出口网上的大部分代码都会 ...
- django后台返回html字段会产生XSS防护的解决方式
1.在前端模块里面写 {{ page_str|safe }} 2.在后端 from django.utils.safestring import mark_safe pake_str = mark_ ...
- python查询mysql中是否存在某张表(传参)
客户端输入了表的名字,服务端判断表是否存在. 参考:https://blog.csdn.net/qq_36523839/article/details/80639297 需要导入re模块: impor ...
- 图解Qt安装(Linux平台)
http://c.biancheng.net/view/3886.html Linux 发行版虽然众多,但 Qt 安装过程大同小异,本节以 CentOS 7 为例来演示 Qt 的安装. 在<Qt ...
- 使用node来搭建简单的后台业务
现在作为一个前端开发人员,越来越多的技术需要学习,近几天学习了下node.js,在很多前端以及后端应用了该技术,现在记录下自己摸索的一些简单的知识记录下来. 我的博客都是直接分享应用方法,没有说明一些 ...