默认参数会覆盖 mypy 的类型提示吗? [英] Does a default parameters overwrite type hints for mypy?

查看:50
本文介绍了默认参数会覆盖 mypy 的类型提示吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码按预期被 mypy 拒绝:

def foo(value: int) ->没有任何:打印(值,类型(值))foo(无)

输出:

错误:参数 1 为foo";具有不兼容的类型无";预期的int"

但是引入了一个None的默认参数后,就没有错误了:

def foo(value: int=None) ->没有任何:打印(值,类型(值))foo(无)

如果我们从 int<更改 value,我希望 mypy 只允许 None(作为参数和默认值)/code> 到 Optional[int],但似乎不需要.为什么?

解决方案

当您让关键字参数接受 None 时,mypy 将隐式地使该参数的类型为 Optional[Blah] 如果还没有.您可以通过将 reveal_type(...) 函数添加到您的代码并运行 mypy 来亲眼看到这一点:

def foo(value: int = None) ->没有任何:打印(值,类型(值))揭示类型(富)foo(无)

输出将是:

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

(请务必在实际运行代码之前删除 reveal_type,因为该函数在运行时实际上并不存在——它只是 mypy 的特殊情况以帮助调试.)>

这种行为的存在主要是因为它有助于减少函数签名的噪音.毕竟,如果 value 在某个时候允许为 None,显然它必须同时接受整数和 None.在这种情况下,为什么不只是将类型推断为 Optional[None](相当于 Union[int, None],顺便说一句),这样用户就不会需要重复两次相同的信息?

当然,并非所有人都喜欢这种行为:有些人更喜欢表现得更直白.在这种情况下,使用 --no-implicit-optional 标志运行 mypy.这将产生以下输出:

test.py:1: 错误:参数value"的默认值不兼容(默认类型为None",参数类型为int")test.py:4: 错误: 显示类型是def (value: builtins.int =)"test.py:5: 错误:foo"的参数 1 具有不兼容的类型无";预期的int"

当然,您需要更改函数签名.

如果您想以其他各种方式提高 mypy 的严格性,请尝试传入 --strict 标志.这将自动启用 --no-implicit-optional 和其他几个严格标志.有关更多详细信息,请运行 mypy --help.

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?

解决方案

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.

这篇关于默认参数会覆盖 mypy 的类型提示吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆