告别复杂判断!Python 中实现函数重载的终极技巧

news/2024/11/13 12:35:07/文章来源:https://www.cnblogs.com/bkbk123/p/18538519

引言
说到函数重载,学过 Java 的同学应该不陌生,最常用的地方应该就是打印 log 了,对于不同的参数,调用的是不同的重载函数。那么 Python 如何实现函数重载呢?

重载概念
函数重载是指在同一作用域内,允许多个同名函数存在,但它们的参数列表不同。虽然许多编程语言(如 Java 和 C++)支持函数重载,但 Python 的设计哲学使其不能直接支持这一特性。

不使用重载
先看一个例子,在不使用重载的情况下,实现一个 log 函数:

from attr import dataclass

@dataclass
class MyException(Exception):
msg: str

def log(message):
if isinstance(message, MyException):
print(message.msg)
elif isinstance(message, str):
print(message)
else:
print(f'invalid message:{message}')

log(MyException('my exception'))
log('str exception')
log(1111)

运行结果为:

my exception

str exception

invalid message:1111

不使用重载的话,就要写很多判断的代码,来判断入参的类型。

使用重载
from functools import singledispatch

from attr import dataclass

@dataclass
class MyException(Exception):
msg: str

@singledispatch
def log(message):
print(f'invalid message:{message}')

@log.register
def _(message: MyException):
print(message.msg)

@log.register
def _(message: str):
print(message)

log(MyException('my exception'))
log('str exception')
log(1111)

运行结果为:

my exception

str exception

invalid message:1111

通过以上代码可以看到,使用重载的情况下,代码简洁了很多,将之前的 if-else 判断都去掉了,每个重载函数根据对应的类型直接输出对应的日志,说明在调用函数时,会自动判断函数的参数类型,然后调用对应的重载函数来执行对应的逻辑。

如果有新增类型的需求,只需要在原有的基础上增加一个重载函数即可,大大简化了新增类型的难度。例如:

from functools import singledispatch

from attr import dataclass

@dataclass
class MyException(Exception):
msg: str

@singledispatch
def log(message):
print(f'invalid message:{message}')

@log.register
def _(message: MyException):
print(message.msg)

@log.register
def _(message: str):
print(message)

@log.register
def _(message: int):
print(f'int message:{message}')

log(MyException('my exception'))
log('str exception')
log(1111)

运行结果为:

my exception

str exception

int message:1111

重载写法
通过以上的代码,总结 Python 通过 functools.singledispatch 进行重载的写法。

首先定义一个函数,加上 @singledispatch 装饰器

然后添加几个以下划线为函数名的函数,因为重载函数的名字都一样,没有必要起其他的名字,用下划线代替即可。

为下划线函数设置对应的函数参数类型,编写函数内容。

调用函数来测试是否生效。

数据类
可能会有小伙伴问,自定义异常上有一个 @dataclass 装饰器,这个是干嘛用的,为什么没有写 init() 函数。

这个装饰器是 Python3.6 中新引入的一个概念,熟悉 Java 的小伙伴可能会知道,它有点类似于 Java 中的 lombok 中的 @data 注解。它的作用是自动为用户自定义的类添加生成的特殊方法,例如 init() 和 repr()。

from dataclasses import dataclass

@dataclass
class InventoryItem:
"""Class for keeping track of an item in inventory."""
name: str
unit_price: float
quantity_on_hand: int = 0

def total_cost(self) -> float:return self.unit_price * self.quantity_on_hand

上面的类不需要单独再写下面的函数,@dataclass 装饰器会自动生成。

def init(self, name: str, unit_price: float, quantity_on_hand: int = 0):
self.name = name
self.unit_price = unit_price
self.quantity_on_hand = quantity_on_hand

cfqw.seemlgo.com
cfqw.shyachao.com
cfqw.dhl-d.com
cfqw.tajqzl.com
cfqw.hzsunbyte.com
cfqw.tjzxjy.com
cfqw.qrpress.com
cfqw.zhanhao118.com
cfqw.marsdrinkschina.com
cfqw.xjlqcl.com
cfqw.5000news.com
cfqw.2500trip.com
cfqw.htsyfs.com
cfqw.hmgjjd.com
cfqw.tcccpsb.com
cfqw.hfsmttp.com
cfqw.nnlianbao.com
cfqw.xinchengabc.com
cfqw.njns56.com
cfqw.gzlcjzs.com
cfqw.xinlvchuang.com
cfqw.juanbanjicj.com
cfqw.tongtaijituan.com
cfqw.lydsmp.com
cfqw.shinenergygroup.com
cfqw.jingranchimian.com
cfqw.tj-shengming.com
cfqw.njxlkhs.com
cfqw.shzljr.com
cfqw.guanlinyouxuan.com
cfqw.ynyoutu.com
cfqw.jiadalong.com
cfqw.jumeizi.com
cfqw.zhs888.com
cfqw.cnaoxin.com
cfqw.afu365.com
cfqw.tzhyex.com
cfqw.xincaiit.com
cfqw.senmaohuanbao.com
cfqw.bjqunlemuye.com
cfqw.lxtxqh.com
cfqw.yuchentimes.com
cfqw.hebeihongqi.com
cfqw.ssyhmma.com
cfqw.hyl98.com
cfqw.youhezhixuan.com
cfqw.jilinsport.com
cfqw.wychyq.com
cfqw.gdhrgk.com
cfqw.jzha101.com
cfqw.lutuohb.com
cfqw.sgxinfeng.com
cfqw.bjyongxuan.com
cfqw.jxtrfund.com
cfqw.fyjyzsgs.com
cfqw.zgygzl.com
cfqw.clwzycgp.com
cfqw.wencfcw.com
cfqw.zmuoo.com
cfqw.xphysc.com
cfqw.kalilan.com
cfqw.jiexinlong.com
cfqw.shiyongsh.com
cfqw.myjhedu.com
cfqw.xczipper.com
cfqw.yjlzk.com
cfqw.huangpihushuichan.com
cfqw.yifanyuanyang.com
cfqw.dianyunzhisheng.com
cfqw.jx-tq.com

所以 @dataclass 可以帮助我们简化代码,提升开发效率,具体的用法可以参考官方文档。

总结
在 Python 中,虽然不支持传统的函数重载,但我们可以通过 functools.singledispatch 方法来实现类似的功能。同时,需要注意一下,只有第一个参数的不同类型会被重载,后面参数的类型变化会被忽略。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python decimal模块用法

decimal 模块:decimal意思为十进制,这个模块提供了十进制浮点运算支持1.可以传递给Decimal整型或者字符串参数,但不能是浮点数据,因为浮点数据本身就不准确。在Python中,将变量声明为 Decimal 类型通常用于需要高精度和小数运算的场合。Decimal 类型属于 decimal 模块,提…

使用Visual Studio Code 快速新建Net项目

前言最近,总是听大家说Visual Studio Code写后端代码非常好用,蓝后,就自己亲身体验了一下,还是很香的。正文1.首先需要安装Dotnet SDK,我这里安装的8.0版本,如下图:2.安装完DotNet SDK,就可以使用命令创建控制台应用了,如下图:3.新建的控制台应用如下图,有一丢丢的简…

20222402 2024-2025-1《网络与系统攻防技术》实验四实验报告

一、实验内容 本周学习内容 计算机病毒(Virus):通过感染文件(可执行文件、数据文件、电子邮件等)或磁盘引导扇区进行传播,一般需要宿主程序被执行或人为交互才能运行 蠕虫(Worm):一般为不需要宿主的单独文件,通过网络传播,自动复制通常无需人为交互便可感染传播 恶意移动代码…

GeoHash处理经纬度,降维,空间填充曲线

个人博客:无奈何杨(wnhyang) 个人语雀:wnhyang 共享语雀:在线知识共享 Github:wnhyang - Overview参考 https://segmentfault.com/a/1190000042971576 GeoHash原理以及代码实现_geohash编码-CSDN博客 GeoHash代码实现--java_geohash java代码示例-CSDN博客 在线经纬度距离…

windows环境下cmd窗口打开就进入到对应目录,一般人都不知道~

前言 很久以前,我还在上一家公司的时候,有一次我看到我同事打开cmd窗口的方式,瞬间把我惊呆了。原来他打开cmd窗口的方式,不是一般的在开始里面输入cmd,然后打开cmd窗口。而是另外一种方式。 我这个同事是个技术控,喜欢研究新的技术,研究一些提高效率的小窍门。这一方面…

黑马PM- B端产品-客户管理

客户管理公海管理商机管理

C盘满了,C盘无损扩容,简单实现

C盘爆满原因很多,无外乎当年固态硬盘贵,C盘分区过小,或者装系统时无意把分区分的太小,这就造成了一个困扰,C盘满了,变成红色,造成软件无法运行,电脑无法启动。如果重新分区,电脑上的资料就没了,所以今天就来介绍一款不用重装系统,扩充C盘容量的方法,操作非常简单,…

SchedulingConfigurer 实现定时任务(动态修改cron,解决@Scheduled需重启服务问题)

通过实现Sc接口,实现定时任务,解决@Scheduled的定时任务改动cron需要服务重启的问题。@Slf4j @Component public class ATestScheduleJob implements SchedulingConfigurer {@Value("${a.c:0/5 * * * * ?}")private String cron1;@Overridepublic void configureT…

20222319 2024-2025-1 《网络与系统攻防技术》实验四实验报告

1.实验要求 1.1 实验内容 一、恶意代码文件类型标识、脱壳与字符串提取 对提供的rada恶意代码样本,进行文件类型识别,脱壳与字符串提取,以获得rada恶意代码的编写作者,具体操作如下: (1)使用文件格式和类型识别工具,给出rada恶意代码样本的文件格式、运行平台和加壳工具…

黑马PM- B端产品- CRM产品概述

CRM的定义CRM的核心要素CRM的设计思路

推荐模型梳理

Summary 目录Summary标准序列推荐模型其他推荐模型FPMCDNN(Pooling)GRU4Rec(RNN-based)GRU4Rec+(RNN-based)Caser(CNN-based)SASRec(Transformer-based)DIN(Transformer-based)BERT4Rec(Transformer-based)TiSASRec(Transformer-based)FMLP-Rec(Transformer-b…