Python_015(面向对象(接口类,抽象类,多态,封装)
Posted pythonZhou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python_015(面向对象(接口类,抽象类,多态,封装)相关的知识,希望对你有一定的参考价值。
一.抽象类与接口类
1.抽象类:抽象即类似或者说比较像的部分,继承描述的是父类与子类的一种关系,要找出这种关系,必须先抽象再继承;
a:抽象分成两个层次:
1)由对象->类:将两个有相似地方的对象抽取成类;
2)由类->父类:将两个有相似地方的类抽取成父类;
:抽象最主要的作用就是划分类别(可以隔离关注点,降低复杂度)
2.为什么要有抽象类
与Java一样,Python也有抽象类的概念,需要借助模块实现,它是一个特殊的类,特殊之处在于只能被继承,不能被实例化;
类是从一些对象中抽取相同的内容而来的,那如果类中有相似的地方,就引出了抽象类概念,
所以从实现的角度来看,抽象类与普通类的不同之处在于:抽象类只能有抽象方法(没有实现功能),这个类不能被实例化,只能被继承,且子类必须实现抽象方法;
#用代码来表示一下接口类和抽象类:
1 #版本一 2 class Alipay: 3 def __init__(self,money): 4 self.money = money 5 def pay(self): 6 print(‘阿里支付了%s元!‘ % self.money) 7 class Jdpay: 8 def __init__(self,money): 9 self.money = money 10 def pay(self): 11 print(‘京东支付了%s元!‘ % self.money) 12 p1 = Alipay(1000) 13 p1.pay() #这里是Alipay.pay() 14 p2 = Jdpay(1000) 15 p2.pay() #这里是Jdpay.pay() 16 #输出结果: 17 阿里支付了1000元! 18 京东支付了1000元!
#虽然你调用pay方法格式没有错,但是不合理,工作中如果有人接着你的程序写一个微信支付,它写的格式和你的可能就不一样,不能体现归一化的设计理念;
2)所以引出第二版(接口的概念)
a:接口提取了一群类共同的函数,可以把接口当做一个函数的集合,然后让子类去实现接口中的函数
这么做的意义在于归一化,归一化就是只要基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,
从用法上来说都一样;
归一化的好处在于:
1. 归一化让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。
2. 归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合
代码展示:
1 #版本二 2 class Alipay: 3 def __init__(self,money): 4 self.money = money 5 def pay(self): 6 print(‘阿里支付了%s元!‘ % self.money) 7 class Jdpay: 8 def __init__(self,money): 9 self.money = money 10 def pay(self): 11 print(‘京东支付了%s元!‘ % self.money) 12 def pay(obj): #接口函数(约定俗成,内行程序员大家都看的懂) 13 obj.pay() 14 p1 = Alipay(1000) 15 pay(p1) 16 p2 = Jdpay(1000) 17 pay(p2) 18 #输出结果: 19 阿里支付了1000元! 20 京东支付了1000元!
**这种做法相对于有素质的程序员行,但是万一来个野生程序员,还按版本一的方式写,就又乱套了;
所以引出第三种写法:抽象类(类似于接口)起规范化作用:
1 class Pay(metaclass=ABCMeta): 2 all_type = ‘alex‘ 3 @abstractmethod #每一个子类中都要有这个方法,定义格式 4 def pay(self):pass #规范一个方法上面加一句@abstractmethod 5 class Alipay(Pay): 6 def __init__(self,money): 7 self.money = money 8 def pay(self): 9 print(‘阿里支付了%s元!‘ % self.money) 10 class Jdpay(Pay): 11 def __init__(self,money): 12 self.money = money 13 def pay(self): 14 print(‘京东支付了%s元!‘ % self.money) 15 class Wxpay(Pay): 16 def __init__(self,money): 17 self.money = money 18 def wupay(self): #这里没有pay方法,再实例化对象时会报错 19 pass 20 p1 = Wxpay(200) 21 #输出结果: 22 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这个名字访问到。
所以在函数外部,你若想要访问函数私有变量或方法,只需要在前面加上_类名__方法名()即可;
以上是关于Python_015(面向对象(接口类,抽象类,多态,封装)的主要内容,如果未能解决你的问题,请参考以下文章