Does a default parameters overwrite type hints for mypy?

不羁的心 提交于 2021-01-22 06:37:13

问题


The following code is rejected by mypy as expected:

def foo(value: int) -> None:
    print(value, type(value))
foo(None)

output:

error: Argument 1 to "foo" has incompatible type "None"; expected "int"

But after introducing a default parameter of None, there is no error anymore:

def foo(value: int=None) -> None:
    print(value, type(value))
foo(None)

I would expect mypy to only allow None (as argument and as the default) if we change value from int to Optional[int], but it seems like this is not needed. Why?


回答1:


When you make a keyword argument accept None, mypy will implicitly make that argument be of type Optional[Blah] if it isn't already. You can see this for yourself by adding the reveal_type(...) function to your code and running mypy:

def foo(value: int = None) -> None:
    print(value, type(value))

reveal_type(foo)
foo(None)

The output would be:

test.py:4: error: Revealed type is 'def (value: Union[builtins.int, None] =)'

(Be sure to delete reveal_type before actually running your code though, since the function doesn't actually exist at runtime -- it's just special-cased by mypy to help with debugging.)

This behavior exists mostly because it helps makes the signatures of functions less noisy. After all, if value, at some point, is allowed to be None, clearly it must accept both ints and None. In that case, why not just infer the type to be Optional[None] (which is equivalent to Union[int, None], btw) so the user doesn't need to repeat the same info twice?

Of course, not everybody likes this behavior: some people prefer being more explicit. In that case, run mypy with the --no-implicit-optional flag. That will produce the following output:

test.py:1: error: Incompatible default for argument "value" (default has type "None", argument has type "int")
test.py:4: error: Revealed type is 'def (value: builtins.int =)'
test.py:5: error: Argument 1 to "foo" has incompatible type "None"; expected "int"

You'd need to change your function signature though, of course.

If you'd like to raise the strictness of mypy in various other ways, try passing in the --strict flag. That will automatically enable --no-implicit-optional and several other strictness flags. For more details, run mypy --help.



来源:https://stackoverflow.com/questions/51055952/does-a-default-parameters-overwrite-type-hints-for-mypy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!