如何正确地实现虚拟类?

news2025/1/9 16:24:46

在 Python 中,所谓的虚拟类通常是指抽象基类(Abstract Base Class,简称 ABC)。抽象基类不可实例化,其主要作用是定义一组抽象方法,子类必须实现这些抽象方法才能被实例化。

要正确实现虚拟类(抽象基类),可以按照我下文写的步骤来。

在这里插入图片描述

1、问题背景

在类继承、抽象基类甚至python接口的文档中,没有一种方式能够完全满足需求。当调用虚拟类时,希望它能够根据给定参数实例化一些更具体的类,并将该类返回给调用函数。

在现有的实现中,通过一种汇总方式将对虚拟类的调用重定向到基础类。思路如下:

class Shape:
    def __init__(self, description):
        if   description == "It's flat":  self.underlying_class = Line(description)
        elif description == "It's spiky": self.underlying_class = Triangle(description)
        elif description == "It's big":   self.underlying_class = Rectangle(description)
    def number_of_edges(self, parameters):
        return self.underlying_class(parameters)

class Line:
    def __init__(self, description):
        self.desc = description
    def number_of_edges(self, parameters):
        return 1

class Triangle:
    def __init__(self, description):
        self.desc = description
    def number_of_edges(self, parameters):
        return 3

class Rectangle:
    def __init__(self, description):
        self.desc = description
    def number_of_edges(self, parameters):
        return 4

shape_dont_know_what_it_is = Shape("It's big")
shape_dont_know_what_it_is.number_of_edges(parameters)

这种重定向方式并不理想,因为它只适用于对number_of_edges()函数的调用,并且向Shape类添加类似以下内容似乎也无法解决问题:

def __getattr__(self, *args):
    return underlying_class.__getattr__(*args)

2、解决方案

有一些方法可以解决这个问题:

方法1:使用__new__方法

class Shape(object):
    def __new__(cls, *args, **kwargs):
        if cls is Shape:                            # <-- required because Line's
            description, args = args[0], args[1:]   #     __new__ method is the
            if description == "It's flat":          #     same as Shape's
                new_cls = Line
            else:
                raise ValueError("Invalid description: {}.".format(description))
        else:
            new_cls = cls
        return super(Shape, cls).__new__(new_cls, *args, **kwargs)

    def number_of_edges(self):
        return "A shape can have many edges…"

class Line(Shape):
    def number_of_edges(self):
        return 1

class SomeShape(Shape):
    pass


>>> l1 = Shape("It's flat")
>>> l1.number_of_edges()
1
>>> l2 = Line()
>>> l2.number_of_edges()
1
>>> u = SomeShape()
>>> u.number_of_edges()
'A shape can have many edges…'
>>> s = Shape("Hexagon")
ValueError: Invalid description: Hexagon.

方法2:使用工厂函数

def factory(description):
    if   description == "It's flat":  return Line(description)
    elif description == "It's spiky": return Triangle(description)
    elif description == "It's big":   return Rectangle(description)

或:
def factory(description):
    classDict = {"It's flat":Line("It's flat"), "It's spiky":Triangle("It's spiky"), "It's big":Rectangle("It's big")}
    return classDict[description]

并从Shape继承类
class Line(Shape):
    def __init__(self, description):
        self.desc = description
    def number_of_edges(self, parameters):
        return 1

对于方法3,Python中没有开箱即用的虚拟类,需要自行实现(这应该是可能的,Python的反射能力足以实现这一点)。然而,如果需要使用虚拟类,建议使用具有虚拟类的编程语言,如Beta、gBeta或Newspeak。不过,在具体的示例中,并不清楚虚拟类如何简化解决方案,或者为什么需要使用虚拟类。

在这几个例子中:

  • Animal 是一个抽象基类,定义了一个抽象方法 make_sound
  • DogCatAnimal 的具体子类,它们必须实现 make_sound 方法才能被实例化。
  • 如果某个子类没有实现抽象基类中的所有抽象方法,尝试实例化该子类会引发 TypeError

注意事项:

  • 抽象基类本身不能被实例化,只能用作其他类的基类。
  • 子类必须实现抽象基类中的所有抽象方法,否则会导致运行时错误。
  • 抽象基类可以包含具体方法,这些方法可以被子类继承或重写。
  • 使用抽象基类能够帮助你设计更加规范和易于维护的类层次结构,强制执行接口和方法的一致性。

通过合理使用抽象基类,可以提高代码的可读性和可维护性,同时在设计接口时提供更好的约束和规范。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1984214.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

新时代来临,跟60后、70后的奢侈消费观念说拜拜吧!

在长达几十年的改革开放壮丽征程中&#xff0c;60后与70后的消费观念深刻塑造了家庭经济的面貌&#xff0c;他们倾尽所有为子女铺设未来之路&#xff0c;从婚房婚车到教育投资&#xff0c;无一不体现了深沉的父爱母爱。然而&#xff0c;随着时代的变迁&#xff0c;尤其是当中国…

连接数据库报错bad handshake

堡垒机账号没有授权访问权限

【xml文档的读取与导入】

首先基于unity引擎&#xff0c;关于xml文档的导入只需要Excel与笔记本两种 打开记事本编写xml代码如下 <?xml version"1.0" encoding"UTF-8"?> <root> <item ID""> <surname></surname> &…

2024开学季必备物品有哪些?新学期学生必备必备物品清单

临近开学&#xff0c;萌新们是否已经开始准备学习物品了呢&#xff1f;正在准备的你&#xff0c;头脑里一定有满满的问号感到头大&#xff0c;不用担心&#xff01;学长学姐们为你准备了详细的开学物品清单&#xff0c;到处搜攻略不如直接看此篇清单&#xff01;快来一起看看吧…

Eclipse 2024 下载 安装 汉化

1&#xff0c;解压 Eclipse 2024 压缩包到当前目录下&#xff1a; 点击此处蓝色字体下载压缩包 提取码 j5nl 2&#xff0c;鼠标右键 点击 jdk-19_windows-x64_bin.exe 选择 以管理员身份运行 &#xff1a; 3&#xff0c;点击 下一步&#xff1a; 4&#xff0c;点击 更改 选择位…

fscan安装

windows安装 1.go语言下载。 下载msi版本&#xff0c;直接安装就可以不用配置环境变量&#xff0c;默认是帮你安装配合好的 All releases - The Go Programming Language 2.配置go环境 使用默认配置的话&#xff0c;下载速度过慢&#xff0c;导致无法完成编译。故需要配置代理…

sql注入——sqlilabs1-15

目录 sql注入靶场练习--sqlilabs 1.less-1​编辑 1.测试发现单引号为逃逸符号 2.确定查询列数为三列 3.查询到数据库名 4.查询数据库中的表名 5.查询用户表的列名字 6.查询用户信息 2.less-2​编辑 2.确定查询列数为三列 3.查询到数据库名 4.查询数据库中的表名 5.…

html实现好看的塔罗牌、十二星座运势网站源码

文章目录 1.设计来源1.1 十二星座1.2 所有界面效果图 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/deta…

几种显微镜的作用(光片,多光子)

若进行细胞的成像&#xff0c;我们通常使用宽场或者共聚焦显微镜&#xff1b;若想要对长时间发育的类器官进行快速成像&#xff0c;则活细胞成像仪是首选&#xff1b;若涉及小鼠整个器官的成像&#xff0c;则会选用双光子显微镜。由此可见&#xff0c;针对不同尺度的样品成像需…

<数据集>灭火器识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;3262张 标注数量(xml文件个数)&#xff1a;3262 标注数量(txt文件个数)&#xff1a;3262 标注类别数&#xff1a;1 标注类别名称&#xff1a;[extinguisher] 使用标注工具&#xff1a;labelImg 标注规则&#xf…

材料学子终于迎来了春天,这3本SCI退稿率<20%,2个录用!

导师逼发顶刊&#xff0c;毕不了业&#xff1f;怎么办? 想拿奖学金&#xff0c;还差一篇SCI&#xff1f; 心仪工作对SCI论文有要求&#xff0c;自己没有? 别慌~准确找到一个命中率高&#xff0c;审稿周期短的期刊真的是省心又省力。 今天&#xff0c;老毕给大家分享3本材料科…

表字段显示tip

需求背景&#xff1a; 生成的报表&#xff0c;前端只展示字段名称&#xff0c;计算逻辑没有解释&#xff0c;使用方频繁“骚扰”&#xff0c;实在受不了&#xff0c;增加一个字段tip&#xff0c;实现效果&#xff08;下图&#xff09;&#xff1a; 代码 结合使用el-table-colu…

go语言day21 goland使用gin框架、gorm框架操作mysql数据库redis数据库 使用宝塔创建redis数据库 写一个投票项目

GORM 指南 | GORM - The fantastic ORM library for Golang, aims to be developer friendly. gorm package - github.com/jinzhu/gorm - Go Packages go语言day20实现投票功能项目包-CSDN博客 基于Redis的有序集合Sorted Sets优化排行榜功能_哔哩哔哩_bilibili 安装gorm框架…

快建屋:革新传统的气膜建筑—轻空间

在建筑行业中&#xff0c;传统建筑方式往往受到施工周期长、成本高、环境影响大等问题的困扰。然而&#xff0c;随着科技的发展和人们对灵活、环保建筑需求的增加&#xff0c;一种全新的建筑形式——快建屋&#xff0c;应运而生。快建屋是一种基于气膜技术的建筑&#xff0c;以…

高考杂志高考杂志社高《高考》杂志社2024年第20期目录

高考论坛 以作业设计为驱动&#xff0c;新高考背景下物理高效课堂构建探析 楚向义; 3-5 新高考化学试题情境考查特点及对情境教学的启示 李瑜; 6-8《高考》投稿&#xff1a;cn7kantougao163.com 高考综合改革背景下高中语文单元主题阅读教学研究 刘春红; 9-11 …

扫地机器人MES系统:功能解析与智能化生产解决方案

扫地机器人MES系统&#xff08;Manufacturing Execution System&#xff0c;制造执行系统&#xff09;在扫地机器人制造过程中扮演着重要角色&#xff0c;它主要负责监控、控制和优化整个生产过程。以下是扫地机器人MES系统的功能介绍及解决方案&#xff1a; 一、MES系统功能介…

使用 Toggle 按钮停止循环

1. 问题背景 用户希望使用 wxPython 创建一个带有滑块和按钮的 GUI 界面&#xff0c;当按下按钮时&#xff0c;滑块的值开始增加&#xff0c;当再次按下按钮时&#xff0c;滑块停止增加。但是&#xff0c;用户在循环中使用 time.sleep() 暂停&#xff0c;导致无法在按下按钮后…

第62期|GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以找…

域凭证获取——DCSync

文章目录 一、DCSync简介二、利用DCSync获取域内用户哈希三、DCSync可逆加密利用&#xff08;没搞定&#xff09;四、域外利用DCSync获取域用户哈希&#xff08;待完成&#xff09;五、利用ACL滥用进行DCSync持久化 攻击机kali IP&#xff1a;192.168.111.0 跳板机win7 IP&…

nodeJS的一点个人总结

nodejs 并不是JavaScript应用&#xff0c;也不是编程语言&#xff0c;因为编程语言使用的JavaScript,Nodejs是 JavaScript的运行时。这个**“运行时”**概念很重要&#xff0c;理解了这个&#xff0c;就理解了nodeJS。 • Node.js并不是JavaScript应用&#xff1a;这里的"…