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

原文地址:https://www.cnblogs.com/dengl/p/11164662.html

时间: 2024-12-21 03:29:40

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

Python进阶(十)----规范化格式目录, time模块, datatime模块,random模块,collection模块(python额外数据类型)

Python进阶(十)----规范化格式目录, time模块, datatime模块,random模块,collection模块(python额外数据类型) 一丶规范化格式目录 六个目录: #### 对某某项目进行一个标准化的开发,进行规范化. #bin : 启动项目程序的主入口 #conf : 项目的配置文件 #core : 主要逻辑(业务逻辑) #db : 存放数据() #lib : 辅助文件(存放公共的一些方法) #README : 项目文档说明 ? 二丶time模块(时间模块) 时间的三

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

Python进阶(十二)----re模块 一丶re模块 ? re模块是python将正则表达式封装之后的一个模块.正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引擎执行. #正则表达式: 从一串字符中,找出你想要的字符串. import re ### 单个元字符的匹配 # \W 除了数字 ,字母,中文, 下划线 print(re.findall('\W','dsadas1231 +1-+2*/,.')) # \w 匹配中文,数字,字母,下划线 print(re.findall('\w

16. 蛤蟆的数据结构进阶十六排序实现之基数排序

16. 蛤蟆的数据结构进阶十六排序实现之基数排序 本篇名言:"社会犹如一条船 ,每人都要有掌舵的准备.--易卜生" 我们来看下基数排序. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47760601 1.  基数排序 基数排序(radix sort)属于"分配式排序"(distributionsort),又称"桶子法"(bucket sort)或bin sort,顾名思义,

python进阶十_正则表达式(一)

最近状态一直不太好,至于原因,怎么说呢,不好说,总之就是纠结中覆盖着纠结,心思完全不在点上,希望可以借助Python的学习以及博客的撰写来调整回来,有的时候回头想一想,如果真的是我自己的问题呢,以前我经常跟别人说,千万不要怀疑自己,因为很清楚一旦连自己都变的不可信,那这个世界就太疯狂了,当一遍一遍的问我,现在连我自己都快怀疑自己了,我一遍一遍的说服别人,想不到现在竟然需要自己去说服自己,何其的悲哀~ 一.正则表达式基础 1.基本概念 正则表达式是计算机科学的一个概念.正则表达式使用单个字符串来描

Python第十六课(模块3)

Python第十六课(模块3)    >>>思维导图>>>中二青年 模块与包 模块 """ 三种来源 1.内置的 2.第三方的 3.自定义的 四种表示形式 1.py文件(******) 2.共享库 3.文件夹(一系列模块的结合体)(******) 4.C++编译的连接到python内置的 """ 导入模块 """ 先产生一个执行文件的名称空间 1.创建模块文件的名称空间 2.执行模

oldboy 21th day. I love Python. 面向对象之封装, 多态, 继承 三大特性

一, 主要内容: 接口类:( 只是在工作中, 书写的一种规范.) 抽象类: 用处: 在工作中, 如果你要是规定几个类, 必须有一样的方法, 你要是抽象类. 封装: 1, 将一些属性或者方法 (一些有用的信息) 放置在一个空间中. 2, 私有成员的封装:私有静态变量, 私有属性, 私有方法 特点: 在变量前+__双下划线, 并且在类外面,子类访问私有变量,私有方法 是访问不到的. 因为私有成员,在运行时, 都会变成: _类名__变量名 所以你在类的外部,或者派生类中都不可访问. 有些方法, 变量,

面向对象之:封装,多态

python面向对象的三大特性:继承,封装,多态. 1. 封装: 把很多数据封装到一个对象中. 把固定功能的代码封装到一个代码块, 函数, 对象, 打包成模块. 这都属于封装的思想. 具体的情况具体分析. 比如. 你写了一个很牛B的函数. 那这个也可以被称为封装. 在面向对象思想中. 是把一些看似无关紧要的内容组合到一起统一进行存储和使用. 这就是封装. 2. 继承: 子类可以自动拥有父类中除了私有属性外的其他所有内容. 说白了, 儿子可以随便用爹的东西. 但是朋友们, 一定要认清楚一个事情.

Python进阶学习之面向对象

目录 面向对象 私有属性 面向对象 ? python也有面向对象的编程,它与C++中的类有点相似.它也只是运算符重载,继承. class Test: num=0 def __init__(self): # self.num=9 #print结果是9 Test.num=10 #print结果是10 t=Test() print(t.num) 但是在python中类中的变量全是共有的,可以通过Test.num来进行访问:在类中,初始化的构造函数并不是以Test()[Test()方法是C++中的构造函

搭建自己的博客(十六):封装优化阅读量代码

1.将阅读量的代码封装在一个app中,增加扩展性 新建app: python manage.py startapp read_statistics 2.变化的部分 3.上代码 from django.contrib import admin from .models import BlogType, Blog # Register your models here. @admin.register(BlogType) class BlogTypeAdmin(admin.ModelAdmin):