重载后面的可选参数



我有一个类Animal,其方法foo根据布尔参数inplace具有不同的返回类型,该参数遵循可选参数bar。我想重载这个函数,这样如果inplace的值是已知的,返回类型是已知的

下面是我的代码:

# main.py
from __future__ import annotations
from typing import Optional, overload, Literal 

class Animal:
@overload
def foo(self, bar=..., inplace: Literal[False]=...) -> Animal:
...
@overload
def foo(self, bar=..., inplace: Literal[True]=...) -> None:
...
def foo(
self, bar=None, inplace: bool = False
) -> Optional[Animal]:
...

reveal_type(Animal().foo(bar='a'))
reveal_type(Animal().foo(inplace=True))
reveal_type(Animal().foo(inplace=False))
$ mypy main.py
main.py:8: error: Overloaded function signatures 1 and 2 overlap with incompatible return types
main.py:21: note: Revealed type is 'main.Animal'
main.py:22: note: Revealed type is 'None'
main.py:23: note: Revealed type is 'main.Animal'
Found 1 error in 1 file (checked 1 source file)

https://mypy-play.net/?mypy=latest& python = 3.9, = 49要点da369f6343543769eed2060fa61639

如何避免第8行出现Overloaded function signatures 1 and 2 overlap with incompatible return types错误?

这似乎可以工作:

from __future__ import annotations
from typing import Optional, overload, Literal 

class Animal:
# using defaults
@overload
def foo(self, bar=..., inplace: Literal[False]=...) -> Animal: ...
# using inplace = True

# with bar
@overload
def foo(self, bar, inplace: Literal[True]) -> None: ...
# without bar
@overload
def foo(self, *, inplace: Literal[True]) -> None: ...
# with bool
@overload
def foo(self, bar=..., inplace: bool=...) -> Optional[Animal]: ...
def foo(
self, bar=None, inplace = False
):
...

reveal_type(Animal().foo(bar='a'))
reveal_type(Animal().foo(bar='a', inplace=True))
reveal_type(Animal().foo(bar='a', inplace=False))
reveal_type(Animal().foo(inplace=True))
reveal_type(Animal().foo(inplace=False))
reveal_type(Animal().foo())
inplace: bool
reveal_type(Animal().foo(bar='a', inplace=inplace))
reveal_type(Animal().foo(inplace=inplace))

大量的重载,但也许这是不可避免的

下面的问题在mymyy是非常相关的:https://github.com/python/mypy/issues/5486

# main.py
from __future__ import annotations
from typing import Literal, Optional, overload

class Animal:
@overload
def foo(self, bar=..., inplace: Literal[False] = ...) -> Animal:
...
@overload
def foo(self, bar=..., *, inplace: Literal[True]) -> None:
...
def foo(self, bar=None, inplace: bool = False) -> Optional[Animal]:
...

reveal_type(Animal().foo(bar="a"))
reveal_type(Animal().foo(inplace=True))
reveal_type(Animal().foo(inplace=False))
$ mypy main.py 
main.py:21: note: Revealed type is "main.Animal"
main.py:22: note: Revealed type is "None"
main.py:23: note: Revealed type is "main.Animal"

通过在第二次重载时在inplace参数前添加*,,并删除其默认值,它可以按预期工作。这是在这条评论中建议的。

但是,如果您尝试使用位置参数调用该函数,则会引入一个问题:
reveal_type(Animal().foo("a", True))
main.py:25: error: No overload variant of "foo" of "Animal" matches argument types "str", "bool"
main.py:25: note: Possible overload variants:
main.py:25: note:     def foo(self, bar: Any = ..., inplace: Literal[False] = ...) -> Animal
main.py:25: note:     def foo(self, bar: Any = ..., *, inplace: Literal[True]) -> None
main.py:25: note: Revealed type is "Any"
Found 1 error in 1 file (checked 1 source file)

在另一条评论中提到了这个问题,建议添加另一个重载可以解决这个问题。

尝试:

@overload
def foo(self, inplace: Literal[False]=..., bar=...) -> Animal:
...
@overload
def foo(self, inplace: Literal[True], bar=...,) -> None:
...
def foo(self, inplace=False, bar=None):
...

我改变了参数的顺序,否则第二次重载不应该是正确的。

相关内容

  • 没有找到相关文章

最新更新