不能函数重载的Python如何实现“伪重载”
能函数重载的Python如何实现“伪重载”
认清现实吧!函数重载在Python中不存在
首先,Python是一门解释型语言,其解释和执行都是动态的,一个名字可以随时代表其他任何意义,根本不存在重载机制。
例如:
1 |
|
Python解释器执行完line1和line2,得知f
是一个函数,其功能是返回传入的唯一一个参数。
然而,line4和line5会把前两行的f
的意义覆盖掉,执行完line5,Python解释器认为f
是一个只接受两个参数的函数,因为这个函数已经将之前对f
的定义覆盖掉了。
因此运行此代码并不会得到想要的1
和3
,而是会得到报错:TypeError: f() missing 1 required positional argument: 'b'
我好像在写代码的时候见到过Python的重载函数?
有没有一种错觉,觉得好像见到过Python的重载函数呢?
先给大家看一段代码及其运行效果(之后再讲其原理):
1 |
|
推荐将上述代码的line1到line15复制到VsCode中,line16和line17手动打上去
可以发现,当我们在函数f
中输入一个参数1
时,编译器提示:(a: int) -> int
在函数f
中输入两个参数1
和2
时,编译器提示:(a: int, b: int) -> int
执行上述代码,发现f(1)
返回值为1
,f(1, 2)
返回值为1 + 2
的值3
,似乎实现了加法函数
的重载
真实原理解析
Python typing
中的overload
修饰器只接收函数的函数名、参数类型及函数的返回类型,并不管函数中具体是什么。
这也就是为什么上述代码的line5和line9都是...
。这里写什么都是不会实际执行的(来自我的观测,未经科学考证)
实际上,真正的函数f
只有line11这一个,这个函数接受可变数量的参数,并将所有接受的到的参数累加后返回。
删掉line1到line10,从line11开始写,执行结果是一模一样的。@overload
修饰器实际上只是对Python的注解的一种扩展
至于VsCode等编辑器为什么会认可这种拓展,是约定俗成还是@overload修饰器有着更深层的秘密?我暂未探究。
好了,懂得了上述原理,我们就可以实现一个“重载之加法器”:
1 |
|
- 当输入
MyAdd(1)
时编辑器会提示(first: int) -> int
- 当输入
MyAdd(1, 2)
时编辑器会提示(first: int, second: int) -> int
- 当输入
MyAdd(1, 2, 3)
时编辑器会提示(first: int, second: int, third: int) -> int
- 当输入
MyAdd(1, 2, 3, 4)
或MyAdd(更多参数)
时编辑器会提示(first: int, second: int, third: int, *more: Any) -> int
运行结果:
1 |
|
是不是很像重载了MyAdd
函数?
弦外音
当然,也可以使用typing
的singledispatch
等实现类似的操作:
1 |
|
运行结果:
1 |
|
但是在输入参数的过程中,编译器给的提示都是(*args: Any, **kwargs: Any) -> None
具体原理暂未深究。
总之,使用typing
中的overload
修饰器,可以做到效果不错的“伪重载”。
同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/129738983