mypy 不理解为 None 值引发异常
mypy doesn't undestand raise Exception for None value
我在另一个函数中创建一个函数,如果其中一个变量是 None
以引发 ValueError
。但是mypy看不懂,我的代码是:
from typing import Mapping, Optional, Union
def make_setting(name: str, age: Optional[int], score: Optional[int]) -> Mapping[str, Union[str, int]]:
def check(the_first_name,*arg):
if None in arg:
raise ValueError('The args of "{}" should not be None.'.format(the_first_name))
check(name, age, score)
return make_setting_of_policy(name, age, score)
def make_setting_of_policy(name: str, age:int, score: int) -> Mapping[str, Union[str, int]]:
return {'name':name, 'age':age, 'score':score}
mypy 不理解 make_setting_of_policy
的输入不是 None
,并显示以下错误:
Argument 2 to "make_setting_of_policy" has incompatible type "Optional[int]"; expected "int"
Argument 3 to "make_setting_of_policy" has incompatible type "Optional[int]"; expected "int"
mypy doesn't understand the input of make_setting_of_policy
is not None
是的,问题是关于 type narrowing Optional
参数以删除潜在的 None
。 Mypy 不考虑引发 run-time 异常。最简单的解决方案是直接检查参数(这应该适用于所有支持 PEP 484 的 Python 3.5+ 版本。)
from typing import Mapping, Optional, Union
def make_setting(name: str, age: Optional[int], score: Optional[int]) -> Mapping[str, Union[str, int]]:
if age is not None and score is not None:
return make_setting_of_policy(name, age, score) # runtime type check
else:
raise ValueError('The args of "{}" should not be None.'.format(name)) # runtime exception
def make_setting_of_policy(name: str, age: int, score: int) -> Mapping[str, Union[str, int]]:
return {'name': name, 'age': age, 'score': score}
mypy 结果:
Success: no issues found in 1 source file
如果使用 Python 3.10,您可以使用 TypeGuards,注意其特定规则。
When a conditional statement includes a call to a user-defined type guard function, and that function returns true, the expression passed as the first positional argument to the type guard function should be assumed by a static type checker to take on the type specified in the TypeGuard return type, unless and until it is further narrowed within the conditional code block.
使用 TypeGuard
的解决方案(使用单个参数,因此我们不重复前面示例的缩小)如下所示:
from typing import Mapping, Optional, Union, TypeGuard
def check(args: tuple[str, Optional[int], Optional[int]]) -> TypeGuard[tuple[str, int, int]]:
if None in args:
raise ValueError('The args of "{}" should not be None.'.format(args[0]))
return all(x is not None for x in args)
def make_setting(name: str, age: Optional[int], score: Optional[int]) -> Mapping[str, Union[str, int]]:
the_args = (name, age, score)
# reveal_type(the_args)
if check(the_args):
# reveal_type(the_args)
return make_setting_of_policy(*the_args) # runtime type check
else:
raise ValueError('The args of "{}" should not be None.'.format(name)) # runtime exception
def make_setting_of_policy(name: str, age: int, score: int) -> Mapping[str, Union[str, int]]:
return {'name': name, 'age': age, 'score': score}
mypy 结果:
Success: no issues found in 1 source file
取消注释 reveal_type()
调用使 mypy 显示预期的类型缩小:
Q71223933.py:13: note: Revealed type is "Tuple[builtins.str, Union[builtins.int, None], Union[builtins.int, None]]"
Q71223933.py:15: note: Revealed type is "Tuple[builtins.str, builtins.int, builtins.int]"
但是您的问题中有一个微妙的暗示,即在 def check(the_first_name,*arg)
函数中对 *args
进行类型缩小。使用 Python 3.11 可以使用 PEP 646 -- Variadic Generics, but since your Optional
s where written with Python 3.9 syntax I'm assuming that's beyond the scope of this question, see PEP 604 -- Allow writing union types as X | Y.
我在另一个函数中创建一个函数,如果其中一个变量是 None
以引发 ValueError
。但是mypy看不懂,我的代码是:
from typing import Mapping, Optional, Union
def make_setting(name: str, age: Optional[int], score: Optional[int]) -> Mapping[str, Union[str, int]]:
def check(the_first_name,*arg):
if None in arg:
raise ValueError('The args of "{}" should not be None.'.format(the_first_name))
check(name, age, score)
return make_setting_of_policy(name, age, score)
def make_setting_of_policy(name: str, age:int, score: int) -> Mapping[str, Union[str, int]]:
return {'name':name, 'age':age, 'score':score}
mypy 不理解 make_setting_of_policy
的输入不是 None
,并显示以下错误:
Argument 2 to "make_setting_of_policy" has incompatible type "Optional[int]"; expected "int"
Argument 3 to "make_setting_of_policy" has incompatible type "Optional[int]"; expected "int"
mypy doesn't understand the input of
make_setting_of_policy
is notNone
是的,问题是关于 type narrowing Optional
参数以删除潜在的 None
。 Mypy 不考虑引发 run-time 异常。最简单的解决方案是直接检查参数(这应该适用于所有支持 PEP 484 的 Python 3.5+ 版本。)
from typing import Mapping, Optional, Union
def make_setting(name: str, age: Optional[int], score: Optional[int]) -> Mapping[str, Union[str, int]]:
if age is not None and score is not None:
return make_setting_of_policy(name, age, score) # runtime type check
else:
raise ValueError('The args of "{}" should not be None.'.format(name)) # runtime exception
def make_setting_of_policy(name: str, age: int, score: int) -> Mapping[str, Union[str, int]]:
return {'name': name, 'age': age, 'score': score}
mypy 结果:
Success: no issues found in 1 source file
如果使用 Python 3.10,您可以使用 TypeGuards,注意其特定规则。
When a conditional statement includes a call to a user-defined type guard function, and that function returns true, the expression passed as the first positional argument to the type guard function should be assumed by a static type checker to take on the type specified in the TypeGuard return type, unless and until it is further narrowed within the conditional code block.
使用 TypeGuard
的解决方案(使用单个参数,因此我们不重复前面示例的缩小)如下所示:
from typing import Mapping, Optional, Union, TypeGuard
def check(args: tuple[str, Optional[int], Optional[int]]) -> TypeGuard[tuple[str, int, int]]:
if None in args:
raise ValueError('The args of "{}" should not be None.'.format(args[0]))
return all(x is not None for x in args)
def make_setting(name: str, age: Optional[int], score: Optional[int]) -> Mapping[str, Union[str, int]]:
the_args = (name, age, score)
# reveal_type(the_args)
if check(the_args):
# reveal_type(the_args)
return make_setting_of_policy(*the_args) # runtime type check
else:
raise ValueError('The args of "{}" should not be None.'.format(name)) # runtime exception
def make_setting_of_policy(name: str, age: int, score: int) -> Mapping[str, Union[str, int]]:
return {'name': name, 'age': age, 'score': score}
mypy 结果:
Success: no issues found in 1 source file
取消注释 reveal_type()
调用使 mypy 显示预期的类型缩小:
Q71223933.py:13: note: Revealed type is "Tuple[builtins.str, Union[builtins.int, None], Union[builtins.int, None]]"
Q71223933.py:15: note: Revealed type is "Tuple[builtins.str, builtins.int, builtins.int]"
但是您的问题中有一个微妙的暗示,即在 def check(the_first_name,*arg)
函数中对 *args
进行类型缩小。使用 Python 3.11 可以使用 PEP 646 -- Variadic Generics, but since your Optional
s where written with Python 3.9 syntax I'm assuming that's beyond the scope of this question, see PEP 604 -- Allow writing union types as X | Y.