Python中的@overload装饰器
文章目录
1. 重写(override)与重载(overload)
在静态语言Java中有重写(override)和重载(overload)两个概念。其中重写是指子类对父类中允许访问的方法进行重新编写,重写时方法名,返回值和参数的数目、类型都不能改变。而重载指的是在同一个类里面,方法名相同,但参数不同的两个方法。
1.1 Java中的重写
class Animal {
public void quack() {
}
}
class Duck extends Animal {
public void quack() {
System.out.println("GaGaGa!");
}
}
1.2 Java中的重载
class Duck {
public void quack() {
System.out.println("GaGaGa!");
}
// 该方法是对上面quack方法的重载
public void quack(String mark) {
System.out.printf("GaGaGa! %s", mark);
}
}
2. 一般情况下,Python不允许重载
一般情况下,Python是不允许重载的。以下面这个例子为例,虽然我们定义两个quack函数,但是在局部命名空间下,只有一个quack函数,即后一个quack函数,也就是说后一个函数覆盖了前一个函数。
def quack():
print("Quack: ")
print(quack)
def quack(mark):
print(f"Quack: {mark}")
print(quack)
print(locals())
局部命名空间内只有一个quack函数
在类内部也是这样,不允许方法重载,如
from attr import attr
class Duck:
def quack(self):
print("GaGaGa!")
def quack(self, mark):
print(f"GaGaGa: {mark}")
print(dir(Duck))
d = Duck()
# d.quack() # 会报错
d.quack("I am a duck~") # Output: GaGaGa: I am a duck~
Duck类中只有一个quack方法
3. overload装饰器
很多人认为只要在类方法中加上了@overload装饰器就实现了Python中的方法重载,实际上不是的。在官方文档中是这样介绍@overload装饰器的[1]:
The
@overload
decorator allows describing functions and methods that support multiple different combinations of argument types. A series of@overload
-decorated definitions must be followed by exactly one non-@overload
-decorated definition (for the same function/method). The@overload
-decorated definitions are for the benefit of the type checker only, since they will be overwritten by the non-@overload
-decorated definition, while the latter is used at runtime but should be ignored by a type checker. At runtime, calling a@overload
-decorated function directly will raiseNotImplementedError
.
也就是说,和typing这module里面其他东西的功能一样,@overload装饰器其实只是一种注解/提示:该函数允许传入不同的参数类型组合。最终,所有加了@overload装饰器的方法都会被一个不加装饰器的方法覆盖掉。如
from typing import overload
class Duck:
@overload
def quack(self) -> None: ...
@overload
def quack(self, mark: str) -> None: ...
# 以上两个方法最终会被这个方法覆盖掉
def quack(self, arg=None):
if arg:
print(f"GaGaGa: {arg}")
else:
print("GaGaGa!")
d = Duck()
d.quack() # Output: GaGaGa!
d.quack("I am a duck~") # Output: GaGaGa: I am a duck~