首页 > 其他分享 >多态和鸭子类型

多态和鸭子类型

时间:2024-01-05 20:33:42浏览次数:21  
标签:多态性 self 多态 def 类型 class talk 鸭子

多态和鸭子类型

【一】多态

【1】什么是多态

  • 多态指的是一类事物有多种形态

【2】示例

  • 比如动物有多种形态:猫、狗、猪
import abc


# 同一类事物:动物
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def talk(self):
        pass


# 动物的形态之一:人
class People(Animal):
    def talk(self):
        print('你真帅')


# 动物的形态之二:狗
class Dog(Animal):
    def talk(self):
        print('汪汪汪')


# 动物的形态之三:猪
class Pig(Animal):
    def talk(self):
        print('哼唧哼唧')
  • 文件有多种形态:文本文件,可执行文件
import abc


# 同一类事物:文件
class File(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def click(self):
        pass

# 文件的形态之一:文本文件
class Text(File):  
    def click(self):
        print('open file')

# 文件的形态之二:可执行文件
class ExeFile(File):  
    def click(self):
        print('execute file')

【二】多态性

【1】什么是多态动态绑定(多态性)

  • 多态动态绑定在继承的背景下使用时,有时也称为多态性
  • 多态性是指在不考虑实例类型的情况下使用实例
  • 在面向对象方法中一般是这样表述多态性:
    • 向不同的对象发送同一条消息(!!!obj.func():是调用了obj的方法func,又称为向obj发送了一条消息func)
    • 不同的对象在接收时会产生不同的行为(即方法)。
    • 也就是说,每个对象可以用自己的方式去响应共同的消息。
    • 所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。
  • 比如:老师.下课铃响了(),学生.下课铃响了()
    • 老师执行的是下班操作
    • 学生执行的是放学操作
    • 虽然二者消息一样,但是执行的效果不同

【2】多态性的分类

  • 多态性分为静态多态性和动态多态性

(1)静态多态性

  • 如任何类型都可以用运算符 + 进行运算

(2)动态多态性

import abc


# 同一类事物:动物
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def talk(self):
        pass


# 动物的形态之一:人
class People(Animal):
    def talk(self):
        print('你真帅')


# 动物的形态之二:狗
class Dog(Animal):
    def talk(self):
        print('汪汪汪')


# 动物的形态之三:猪
class Pig(Animal):
    def talk(self):
        print('哼唧哼唧')


peo = People()
dog = Dog()
pig = Pig()

# peo、dog、pig都是动物,只要是动物肯定有talk方法
# 于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
peo.talk()
dog.talk()
pig.talk()


# 更进一步,我们可以定义一个统一的接口来使用
def func(obj):
    obj.talk()
  • Python中一切皆对象,本身就支持多态性
# 我们可以在不考虑三者类型的情况下直接使用统计三个对象的长度
s.__len__()
l.__len__()
t.__len__()

# Python内置了一个统一的接口
len(s)
len(l)
len(t)

【3】为什么要用多态性(多态性的好处)

  • 增加了程序的灵活性
    • 以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal)
  • 增加了程序额可扩展性
    • 通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(animal)去调用
import abc


# 同一类事物:动物
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def talk(self):
        pass


# 属于动物的另外一种形态:猫
class Cat(Animal):
    def talk(self):
        print('喵喵喵')


# 对于使用者来说,自己的代码根本无需改动
def func(animal):
    animal.talk()


# 实例出一只猫
cat1 = Cat()
# 甚至连调用方式也无需改变,就能调用猫的talk功能
func(cat1)
  • 这样我们新增了一个形态Cat,由Cat类产生的实例cat1,使用者可以在完全不需要修改自己代码的情况下。
  • 使用和人、狗、猪一样的方式调用cat1的talk方法,即func(cat1)

【三】鸭子类型 duck-typing

【1】什么是鸭子类型 duck-typing

  • 鸭子类型是一种编程风格,决定一个对象是否有正确的接口
    • 关注点在于它的方法或属性
    • 而不是它的类型(如果它看起来像鸭子,像鸭子一样嘎嘎叫,那么它一定是鸭子。)。
  • 通过强调接口而不是特定类型,设计良好的代码通过多态提高了灵活性。
    • 鸭子类型无需使用 type()isinstance() 进行检查(注意,鸭子类型可以用抽象基类来补充)
    • 相反,它通常使用 hasattr() 来检查,或是 EAFP 编程。
  • 但其实我们完全可以不依赖于继承,只需要制造出外观和行为相同对象,同样可以实现不考虑对象类型而使用对象,这正是Python崇尚的“鸭子类型”(duck typing):
    • “如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子”。
    • 比起继承的方式,鸭子类型在某种程度上实现了程序的松耦合度

【2】鸭子类型

# 二者都像鸭子,因而就可以当鸭子一样去用
class NormalDuck():
    def eat(self):
        print(f"正常鸭子可以吃饭")

    def walk(self):
        print(f"正常鸭子可以走路")


class RockDuck():
    def eat(self):
        print(f"肉鸭子可以吃饭")

    def walk(self):
        print(f"肉鸭子可以走路")

标签:多态性,self,多态,def,类型,class,talk,鸭子
From: https://www.cnblogs.com/banchengyanyu/p/17948028

相关文章

  • 多态
    (一)多态(1)什么是多态多态指的是一类事物有多种形态比如动物---猪狗牛羊(2)示例比如动物有多种形态:猫、狗、猪importabc#同一类事物:动物classAnimal(metaclass=abc.ABCMeta):@abc.abstractmethoddeftalk(self):pass#动物的形态之一:人c......
  • C语言学习随笔-04 数据类型
    C中的数据类型:在C语言中,数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统。变量的类型决定了变量存储占用的空间,以及如何解释存储的位模式。常用的四中基本数据类型:int、char、float、double    ▶基本类型:它们是算术类型,如int、char、float、double。 ......
  • 数据类型、标识符、键盘输入
    数据类型标识符键盘输入此方法只能输入整数......
  • DNS 攻击类型
    目前,针对域名系统(DNS)的攻击已经成为企业组织数字化发展中的一个严重问题,每年都有数千个网站成为此类攻击的受害者。据最近的研究数据显示,2023年企业组织与DNS攻击相关的损失同比增加了49%,这些损失不仅是在企业的财务方面,还包括对组织内部系统和云上应用造成的损害。企业如果要保护......
  • MySQL三大日志,mvcc、DateTime 类型等
    1、MySQL事务隔离级别详解解决幻读的方法解决幻读的方式有很多,但是它们的核心思想就是一个事务在操作某张表数据的时候,另外一个事务不允许新增或者删除这张表中的数据了。解决幻读的方式主要有以下几种:将事务隔离级别调整为 SERIALIZABLE 。在可重复读的事务级别下,给事务操......
  • 在TypeScript中重命名类型索引?
    在TypeScript中,要重命名类型索引,你可以使用TypeScript的类型别名或接口来实现。下面是两种常见的方法:1.使用类型别名(TypeAliases):类型别名允许你为一个类型定义一个别名,通过使用关键字type来创建。你可以在别名中定义索引类型,并为该类型定义一个新的名称。```typescripttypeMy......
  • MySQL 8.0的SQL查询JSON返回的数据类型为字符串而非数组
    在MySQL8.0中,SQL查询JSON返回的数据类型确实是字符串,而不是数组。这是因为MySQL将JSON数据存储为字符串,并提供了一些函数和操作符来处理JSON数据。但是,你可以使用内置的JSON函数来处理返回的JSON字符串。例如,你可以使用JSON_EXTRACT函数来提取JSON字符串......
  • 鸿蒙原生应用/元服务开发-发布进度条类型通知
    进度条通知也是常见的通知类型,主要应用于文件下载、事务处理进度显示。HarmonyOS提供了进度条模板,发布通知应用设置好进度条模板的属性值,如模板名、模板数据,通过通知子系统发送到通知栏显示。目前系统模板仅支持进度条模板,通知模板NotificationTemplate中的data参数为用户自定义数......
  • 封装、继承、多态
    封装、继承、多态1.封装封装就是将属性隐藏,不让外界发现或使用将可以允许外界使用的内容通过接口开发,让用户通过接口使用隐藏属性的方法是通过__变量名1.1封装之隐藏属性隐藏数据属性classTeacher:def__init__(self,name,age):#将名字和年纪都隐藏......
  • 对比 SQL Server中的VARCHAR(max) 与VARCHAR(n) 数据类型
    开始之前:设计某数据库表结构的过程中,收到了一个另外令人感到意外的建议:对于字符型数据类型,数据库里统一使用varchar(max)来存储,也就是所有字符数据类型都用varchar(max)字段类型,理由是ORM写代码方便?是的,你没有听错,为了ORM中写代码方便,所以建议数据库中字符型字段全部使用varchar(......