(转)Python @overload

部署运行你感兴趣的模型镜像

在Python的世界中,我们经常遇到一些看似复杂但实际上非常有用的特性,其中@overload就是一个典型例子。这个高级特性对于理解和编写更加健壮的Python代码至关重要。

首先,让我们解释一下@overload的含义。@overload是Python中的一个函数装饰器,它允许我们为同一个函数定义多个不同的签名。当然实际上Python的函数不支持通过参数类型重载,因此@overload只是为一个函数提供多个类型标注,用于提高代码的可读性。

为了更好地理解这一点,让我们以一个自定义的list of str类为例。假设我们有一个这样的类,其__getitem__方法既可以接受一个下标,也可以接受一个切片对象(slice)。这就是一个典型的使用场景。

from typing import overload, List, Union

class MyStrList:
    def __init__(self, content: List[str]):
        self.content = content

    @overload
    def __getitem__(self, index: int) -> str:
        ...

    @overload
    def __getitem__(self, s: slice) -> 'MyStrList':
        ...

    def __getitem__(self, item: Union[int, slice]) -> Union[str, 'MyStrList']:
        if isinstance(item, int):
            return self.content[item]
        elif isinstance(item, slice):
            return MyStrList(self.content[item])
        else:
            raise TypeError("Invalid argument type.")

data = MyStrList(["hello", ",", "world"])
item = MyStrList.__getitem__(0) # equivalent to `MyStrList[0]`
items = MyStrList.__getitem__(slice(1, 2)) # equivalent to `MyStrList[1:2]`

在这个例子中,我们使用@overload来定义两种不同的__getitem__方法。第一个方法接受一个整数索引,并返回一个字符串;第二个方法接受一个切片对象,并返回一个MyStrList对象。

首先要了解关于...的用法:Python中的...是一个特殊的变量,类似None,上升到了语言的级别,Python识别到了...就会把它对应到一个特殊变量上。a = ...表示a也指向这一变量。type(...)即可看到,它是ellipsis类的一个实例(意为省略号)。因此,这段代码看起来就像是函数体被省略了。

    @overload
    def __getitem__(self, index: int) -> str:
        ...

我们可以进一步查看@overload是怎么实现的:

def _overload_dummy(*args, **kwds):
    """Helper for @overload to raise when called."""
    raise NotImplementedError(
        "You should not call an overloaded function. "
        "A series of @overload-decorated functions "
        "outside a stub module should always be followed "
        "by an implementation that is not @overload-ed.")

def overload(func):
    return _overload_dummy

所以,当我们在函数上加了@overload时,本质上这个函数被替换成了_overload_dummy函数,不能直接调用。

@overload的作用在于提供类型标注。如果没有@overload,我们的函数标注def __getitem__(self, item: Union[int, slice]) -> Union[str, 'MyStrList']表明输入参数可能是int或者slice,输出参数可能是str或者MyStrList。但实际上,输入是int的时候,输出只能是str,不可能是MyStrList。为了表示这种更加复杂的类型关系,我们可以用两个分别的类型标注来进行解释。

加上了@overload之后,编辑器就会识别到这些类型标注,并且给用户更好的提示。

例如上图中,VS code提示了两种类型标注,非常直观。

注意,由于Python实际上并不支持按照函数参数来重载,因此我们必须在代码里自己实现类型相关的逻辑,例如这里代码中的if isinstance(item, int),就是按照参数类型实现不同的操作。

总之,@overload是Python中一个非常强大且有用的功能,它能够增强代码的灵活性和可读性。其核心功能就是把一个复杂函数的各种使用方式通过类型标注提示给用户。

您可能感兴趣的与本文相关的镜像

Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值