热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

Python进阶(十六)面向对象之~封装,多态,鸭子模型,super原理(单继承原理,多继承原理)一丶封装,多态封装:?将一些东西封装到一个地方,你还可以取出来?类设置静态属性,设

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__()
l.__len__()
t.__len__()

len(s)
len(l)
len(t)





#### 例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  按照继承顺序来找, 再执行Foo

class Bar(A):
    def f1(self):
        print('in Bar')     # 1 按照继承顺序来找, 先执行Bar

class Info(Foo,Bar):    

    def f1(self):
        super(Info,self).f1()    # 是从Info当前类开始,
        print('in Info f1')     # 3  按照继承顺序来找, 再执行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原理(单继承原理,多继承原理)


推荐阅读
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文内容为asp.net微信公众平台开发的目录汇总,包括数据库设计、多层架构框架搭建和入口实现、微信消息封装及反射赋值、关注事件、用户记录、回复文本消息、图文消息、服务搭建(接入)、自定义菜单等。同时提供了示例代码和相关的后台管理功能。内容涵盖了多个方面,适合综合运用。 ... [详细]
  • 本文讲述了作者通过点火测试男友的性格和承受能力,以考验婚姻问题。作者故意不安慰男友并再次点火,观察他的反应。这个行为是善意的玩人,旨在了解男友的性格和避免婚姻问题。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
author-avatar
你们聊交给我
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有