【问题标题】:Return type of slice for a user-made container in python返回python中用户制作容器的切片类型
【发布时间】:2021-11-05 19:54:40
【问题描述】:

我正在创建一个自定义容器,它在切片时返回一个自身的实例:

from typing import Union, List

class CustomContainer:
    def __init__(self, values: List[int]):
        self.values = values

    def __getitem__(self, item: Union[int, slice]) -> Union[int, CustomContainer]:
        if isinstance(item, slice):
            return CustomContainer(self.values[item])
        return self.values[item]

这可行,但有以下问题:

a = CustomContainer([1, 2])
b = a[0]  # is always int, but recognized as both int and CustomContainer
c = a[:]  # is always CustomContainer, but recognized as both int and CustomContainer

# Non-scalable solution: Forced type hint
d: int = a[0]
e: CustomContainer = a[:]

如果我将__getitem__ 的返回类型更改为仅int(我的原始方法),则a[0] 正确显示类型int,但a[:] 被视为list 而不是@987654329 @。 据我了解,python2中曾经有一个函数来定义切片的创建方式,但在python3中被删除了。

有没有一种方法可以提供正确的类型提示,而不必每次使用容器时都强制输入类型提示?

【问题讨论】:

    标签: python python-3.x type-hinting python-typing


    【解决方案1】:

    您想使用typing.overload,它允许您使用类型检查器注册函数的多个不同签名。用@overload 装饰的函数在运行时会被忽略,因此您通常只需用文字省略号...pass 或文档字符串填充主体。这也意味着您必须保留至少一个未使用@overload 修饰的函数版本,这将是运行时使用的实际函数。

    如果您查看typeshed,大多数主要类型检查器用于检查标准库的存根文件存储库,您会发现这是他们用于在自定义容器中注释__getitem__ 方法的技术如collections.UserList。在你的情况下,你会像这样注释你的方法:

    from typing import overload, Union, List
    
    class CustomContainer:
        def __init__(self, values: List[int]):
            self.values = values
            
        @overload
        def __getitem__(self, item: int) -> int:
            """Signature when the function is passed an int"""
            
        @overload
        def __getitem__(self, item: slice) -> CustomContainer:
            """Signature when the function is passed a slice"""
    
        def __getitem__(self, item: Union[int, slice]) -> Union[int, CustomContainer]:
            """Actual runtime implementation"""
    
            if isinstance(item, slice):
                return CustomContainer(self.values[item])
            return self.values[item]
    
    a = CustomContainer([1, 2])
    b = a[0]
    c = a[:]
    
    reveal_type(b)
    reveal_type(c)
    

    运行through MyPy,它会告诉我们:

    main.py:24: note: Revealed type is "builtins.int"
    main.py:25: note: Revealed type is "__main__.CustomContainer"
    

    进一步阅读

    @overload 的 mypy 文档可以在 here 找到。

    【讨论】:

    • 谢谢。这正是我所需要的。
    • @Aba 不用担心,很高兴我能帮上忙!
    猜你喜欢
    • 2019-04-09
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 2019-07-29
    • 1970-01-01
    • 2018-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多