Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理)

一丶封装 , 多态

封装:

           将一些东西封装到一个地方,你还可以取出来(把一些内容装到某个容器内,用到这些内容还能取出来)

           类设置静态属性, 设置一些方法 或者 对象, 对象可以在其对象封装一些属性

多态:

           python默认支持多态, 多态指的是一种事务具有多种形态

           多态的优点:

           1.多态可以增加代码的灵活度;

           2.以继承和重写父类方法为前提;

           3.是调用方法的技巧,不会影响到类的内部设计

           个人理解: 接口(存放功能相类似的函数)重用,一种接口多种实现(通过接口调用相对应的函数)

#### 例1:
#序列类型有多种形态:字符串,列表,元组,但他们直接没有直接的继承关系 #str,list,tuple都是序列类型
s=str('hello')
l=list([1,2,3])
t=tuple((4,5,6)) #我们可以在不考虑三者类型的前提下使用s,l,t
s.__len__() # 三者的序列类型 都有__len_()方法,
l.__len__()
t.__len__() len(s) # len函数就具有多种形态
len(l)
len(t) # 解释: len函数就是一种事务, 元组,列表,字符就是多种形态.因为它们三者都含有__len__()函数 #### 例2: import abc
class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
@abc.abstractmethod
def talk(self):
pass class People(Animal): #动物的形态之一:人
def talk(self):
print('say hello') class Dog(Animal): #动物的形态之二:狗
def talk(self):
print('say wangwang') class Pig(Animal): #动物的形态之三:猪
def talk(self):
print('say aoao') peo=People()
dog=Dog()
pig=Pig() #peo、dog、pig都是动物,只要是动物肯定有talk方法
#于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
peo.talk()
dog.talk()
pig.talk() #更进一步,我们可以定义一个统一的接口来使用
def func(obj):
obj.talk()

鸭子模型:是动态类型的一种风格

      定义:

           当看到一只鸟走起来像鸭子,游泳起来像鸭子,叫起来也像鸭子,那么这只鸟就可以被称为鸭子.

      概念:

           在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。例如,在不使用鸭子类型的语言中,我们可以编写一个函数,它接受一个类型为鸭的对象,并调用它的走和叫方法。在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象,并调用它的走和叫方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这样的正确的走和叫方法的对象都可被函数接受的这种行为引出了以上表述,这种决定类型的方式因此得名。鸭子类型通常得益于不测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。从静态类型语言转向动态类型语言的用户通常试图添加一些静态的(在运行之前的)类型检查,从而影响了鸭子类型的益处和可伸缩性,并约束了语言的动态特性。(摘自CSDN juunny,仅供参考)

class A:

    def login(self):
pass def register(self):
pass class B: def login(self):
pass def register(self):
pass # A,B两个类,没有任何关系,独立两个,但是里面的功能相似,所以python一般会将类似于A,B两个类
# 里面的相似的功能让其命名相同.
# A,B虽然无关系,但是很默契的制定了一个规范.让你使用起来更方便. ## 个人理解:
#你可以定义一个公共的接口, 简化代码 .牛逼人都这么干
def func(obj):
obj.register()
obj.login()

       一篇详细的多态文章

二丶类的约束

归一化设计:

           统一接口

###  pay函数就作为 统一的接口  不论用哪个平台调用都是使用pay函数

class QQ(Payment):
def pay(self,money):
print(f'支付了 {money}') class Ali(Payment):
def pay(self,money):
print(f'支付了 {money}') class WeChat(Payment):
def fuqian(self,money):
print(f'支付了 {money}') # 定义接口函数
def pay(obj,money):
obj.pay(money) q=QQ() # 实例化对象
a=Ali()
w=WeChat() pay(q,200) # 调用接口 实现功能
pay(a,100)
pay(w,1200)

父类建立一种约束

### 父类的约束不是强制性的,不重写父类的 pay函数 也可以调用子类本身的函数,完成支付功能

class Payment:			

    def pay(self,money):
raise Exception('子类必须继承父类pay方法') # 当子类执行接口函数时,调用函数名与父类不一致,父类pay函数主动抛出一个异常 class QQ(Payment):
def pay(self,money):
print(f'支付了 {money}') class Ali(Payment):
def pay(self,money):
print(f'支付了 {money}') class WeChat(Payment):
def fuqian(self,money):
print(f'支付了 {money}') # 定义接口 def pay(obj,money):
obj.pay(money) q=QQ() # 实例化对象
a=Ali()
w=WeChat() pay(q,200)
pay(a,100)
pay(w,1200) # 由于 子类没有重写父类的pay方法, 父类会主动抛出一个异常

模拟抽象类(指定一种规范)的概念,建立一种约束.

### 强制性约束, 必须重写父类的方法 

from abc import abstractmethod, ABCMeta  # 导入抽象类 和 抽象元类

class Payment(metaclass=ABCMeta):     # 定义这个类是一个抽象类
@abstractmethod # 给父类的 pay 函数添加抽象方法装饰器. 当子类没有重写父类方法,实例化对象时,就会报错
def pay(self, money):
pass class QQ(Payment):
def pay(self, money):
print(f'支付了 {money}') class Ali(Payment):
def pay(self, money):
print(f'支付了 {money}') class WeChat(Payment):
def fuqian(self, money):
print(f'支付了 {money}') # 重写父类的pay函数,就不会报错. 不重写就会报错
def pay(self, money):
pass # 定义接口 def pay(obj, money):
obj.pay(money) q=QQ()
a=Ali()
w=WeChat() # 1. 实例化对象时, 就会报错. 必须重写父类的pay函数 , pay(q,200)
pay(a,100)
pay(w,1200) # 由于抽象方法引自与Java的抽象类. so 原理相同
### 抽象类 不能被实例化 ,只能被继承
aa=Payment()
# TypeError: Can't instantiate abstract class Payment with abstract methods pay

三丶super的深入理解

### super() 并不是 执行父类的方法

    # 单继承: super() 肯定执行父类的方法

	# 多继承:  super(S,self)严格按照self(就是当前对象) 从属于类的mro的执行顺序,执行 S类的下一位

class A:
def f1(self):
print('in A') class Foo(A):
def f1(self):
super(Foo,self).f1()
print('in Foo') # 2 按照继承顺序来执行,主动执行当前类的下一个类(按照继承顺序执行) , 执行Bar类 class Bar(A):
def f1(self):
print('in Bar') # 1 按照继承顺序来执行, 执行当前类的下一个类(按照继承顺序执行),已经定位到当前的Bar中的f1函数,就不再向上寻找. class Info(Foo,Bar): def f1(self):
super(Info,self).f1() # 从Info当前类开始 ,执行当前类的下一个类(按照继承顺序执行), 执行Foo类, 不写是默认从Info当前类super(Info,self).f1()=super().f1()
print('in Info f1') # 按照继承顺序来执行完毕后, 再执行Info obj = Info()
print(Info.mro()) # obj对象的 继承顺序[Info, Foo, Bar, A]
obj.f1()
# 结果: in Bar, in Foo , in Info f1 ####多继承 , super指定继承哪个类,就从这个类的下一个类执行
class A:
def f1(self):
print('in A') class Foo(A): def f1(self):
super().f1()
print('in Foo') class Bar(A): def f1(self): # self = obj
print('in Bar') class Info(Foo,Bar): def f1(self): # self = obj
super(Foo,self).f1() # 这里指定从Foo类继承. 按照多继承规则,会执行下一个类,也就是Bar
print('in Info f1') obj = Info()
obj.f1() # obj对象的 继承顺序[Info, Foo, Bar, A] # 结果 : in Bar, in Info f1

Python进阶(十六)----面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理)的更多相关文章

  1. Python进阶(十五)----面向对象之~继承(单继承,多继承MRO算法)

    Python进阶(十五)----面向对象之~继承 一丶面向对象的三大特性:封装,继承,多态 二丶什么是继承 # 什么是继承 # b 继承 a ,b是a的子类 派生类 , a是b的超类 基类 父类 # ...

  2. python学习day19 面向对象(一)封装/多态/继承

    面向对象 封装思想:将同一类的函数函数封装到同一个py文件中,方便调用 面向对象也有封装的作用,将同一类的函数封装到一个类中 多态(鸭子模型):多种类型/多种形态 #,什么事鸭子模型 对于一个函数,p ...

  3. J2EE进阶(十六)Hibernate 中getHibernateTemplate()方法使用

    J2EE进阶(十六)Hibernate 中getHibernateTemplate()方法使用   spring 中获得由spring所配置的hibernate的操作对象,然后利用此对象进行,保存,修 ...

  4. Python进阶(十四)----空间角度研究类,类与类之间的关系

    Python进阶(十四)----空间角度研究类,类与类之间的关系 一丶从空间角度研究类 对象操作对象属性 class A(): address = '沙河' def __init__(self, na ...

  5. Python进阶(十二)----re模块

    Python进阶(十二)----re模块 一丶re模块 ​ re模块是python将正则表达式封装之后的一个模块.正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引擎执行. #正则表达式: ...

  6. Python进阶(十)----软件开发规范, time模块, datatime模块,random模块,collection模块(python额外数据类型)

    Python进阶(十)----软件开发规范, time模块, datatime模块,random模块,collection模块(python额外数据类型) 一丶软件开发规范 六个目录: #### 对某 ...

  7. Python 爬虫十六式 - 第六式:JQuery的假兄弟-pyquery

    PyQuery:一个类似jquery的python库 学习一时爽,一直学习一直爽   Hello,大家好,我是 Connor,一个从无到有的技术小白.上一次我们说到了 BeautifulSoup 美味 ...

  8. Python 爬虫十六式 - 第七式:正则的艺术

    RE:用匹配来演绎编程的艺术 学习一时爽,一直学习一直爽   Hello,大家好,我是 Connor,一个从无到有的技术小白.上一次我们说到了 pyquery 今天我们将迎来我们数据匹配部分的最后一位 ...

  9. Python 爬虫十六式 - 第五式:BeautifulSoup-美味的汤

    BeautifulSoup 美味的汤 学习一时爽,一直学习一直爽!    Hello,大家好,我是Connor,一个从无到有的技术小白.上一次我们说到了 Xpath 的使用方法.Xpath 我觉得还是 ...

随机推荐

  1. Spark2.x(六十三):(Spark2.4)Driver如何把Task(闭包等)分配给Executor

    在Spark中一个appliation可能包含多个job,每个job都是由SparkContext#runJob(...)触发的,一个Job下包含1个或多个Stage,Job的最后一个stage为Re ...

  2. 洛谷 P1969 积木大赛(NOIP2013)

    题目描述春春幼儿园举办了一年一度的“积木大赛”.今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi. 在搭建开始之前,没有任何积木(可以看成n ...

  3. lightgbm GPU版本安装

     python机器学习-乳腺癌细胞挖掘(博主亲自录制视频)https://study.163.com/course/introduction.htm?courseId=1005269003&u ...

  4. 2的幂和按位与&——效率

    以前学生时代,只是完成功能就行,进入公司之后,由于产品的特殊性,需要非常考虑效率,发现有以下几个策略(该文不定时更新): hash%length==hash&(length-1)的前提是len ...

  5. LeetCode 112. Path Sum(路径和是否可为sum)

    Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all ...

  6. MathML

    MathML https://developer.mozilla.org/en-US/docs/Web/MathML/Examples/MathML_Pythagorean_Theorem Mathe ...

  7. WordtoPdfUtil word转pdf

    jar: <dependency> <groupId>com.jacob</groupId> <artifactId>jacob</artifac ...

  8. 使用java计算数组方差和标准差

    使用java计算数组方差和标准差 觉得有用的话,欢迎一起讨论相互学习~Follow Me 首先给出方差和标准差的计算公式 代码 public class Cal_sta { double Sum(do ...

  9. 媲美GWAS Catalog,囊括45万人数据,778个表型,3千万个位点的公共数据库:GeneATLAS

    欢迎关注微信公众号"bio生物信息" GeneATLAS的数据全部来自 UK Biobank 的452,264个英国白人样本. 总共囊括的表型有778个,位点有三千万个. 优点 网 ...

  10. Java8 特性

    1.jdk8的特性stream().map() 2.Java8中用Lambda表达式的groupBy合并多个相同属性的对象集合 3.Java8 Stream 语法详解 & 用法实例