python-3.x 如何用str默认值注解一个接受AnyStr的函数?

62lalag4  于 2022-12-14  发布在  Python
关注(0)|答案(3)|浏览(185)

我希望对一个函数进行类型注解,该函数接受一个AnyStr参数,该参数默认为str,并且返回一个相同类型的AnyStr

from typing import AnyStr

def func(s: AnyStr = ".") -> AnyStr:
    return s

则mypy失败,出现“Incompatible default for argument "s" (default has type "str", argument has type "bytes")“。
我还尝试将代码拆分为.py.pyi文件,如下所示:
.py文件:

def func(s = "."):
    return s

.pyi文件:

from typing import AnyStr

def func(s: AnyStr = ...) -> AnyStr:
    ...

...但是我一定是调用mypy错了,因为它无法对func的调用进行类型检查;例如,如果我将func(42)添加到.py文件中,mypy不会抱怨。
正确的方法是什么来注解我的函数并使代码完全经过类型检查?

jutyujz0

jutyujz01#

使用None作为默认值,然后在函数内部使用两种类型转换:一个用于将None替换为.“”,转换为Optional[AnyStr],另一个用于将返回值转换为AnyStr

def func(s : AnyStr = None) -> AnyStr:
    if s is None:
        s = cast(Optional[AnyStr], ".")
    return cast(AnyStr, s)

字符串
EDIT:我最初的答案失败了,因为类型检查忽略了具体的实现:
一种可能性是使用overload来列举AnyStr所涵盖的两种情况:

from typing import overload

@overload
def func(s: str = ".") -> str:
    pass

@overload
def func(s: bytes) -> bytes:
    pass

def func(s):
    return s
unftdfkk

unftdfkk2#

我们讨论了这个案例here,特别是圭多的回答:
我认为这里的问题是,通常情况下,例如,如果有其他参数也在其类型中使用_T,则默认值将不起作用。由于这是唯一的参数,您可以说这是过度限制,如果没有参数,则返回类型应该仅由该默认值确定(在简化的示例中,您希望它返回int),但我并不热衷于这样做,因为只要使用另一个泛型参数,它就会中断。
基于该线程,您可以使用以下解决方法:

from typing import AnyStr, overload

@overload
def func() -> str: ...

@overload
def func(s: AnyStr) -> AnyStr: ...

def func(s = "."):  # unchecked implementation
    return func_internal(s)

def func_internal(s: AnyStr) -> AnyStr:
    # a checked complicated body moved here
    return s
0pizxfdo

0pizxfdo3#

也许这就是你想要的:

@overload
def func(s: str=...) -> str: ...   
@overload
def func(s: bytes) -> bytes: ...
@overload
def func(s: None) -> str: ...    

def func(s="."):
    return s

r1 = func()
reveal_type(r1)
r2 = func("1")
reveal_type(r2)
r3 = func(b"1")
reveal_type(r3)

Mypy: The stdout of the command line is:
note: Revealed type is 'builtins.str'
note: Revealed type is 'builtins.str'
note: Revealed type is 'builtins.bytes'

相关问题