Ola*_*laf 5 python type-hinting argparse mypy
我正在尝试使用 mypy 来检查我的程序。该程序使用 argparse 来解析命令行参数。我想为命令行参数添加类型提示。
import argparse
import typing
# define example types and a function that uses them
Seconds = typing.NewType("Seconds", float)
Minutes = typing.NewType("Minutes", float)
def sec_to_min(s: Seconds) -> Minutes:
return Minutes(s / 60)
# specify arguments and parse them
parser = argparse.ArgumentParser()
parser.add_argument("-t", "--time", default=1., type=float,
help="time in seconds")
args = parser.parse_args()
try:
# mypy reveals type Any
reveal_type(args.time)
except NameError:
pass
# (1) passes type check
seconds: Seconds = args.time
# (2) passes type check
sec_to_min(args.time)
Run Code Online (Sandbox Code Playgroud)
我希望 mypy 识别args.time为Seconds. 当前代码应该识别args.time为浮点数并抱怨,因为也将浮点数传递给了sec_to_min抱怨。
我尝试更改to的type参数。这没有效果,mypy 仍然标识为.
正如这里提到的,我还尝试提供自定义 NameSpace。这将 的显示类型更改为。我想避免这种情况,因为我必须为每个参数复制名称,并且默认值 from被自定义命名空间覆盖。add_argumenttype=lambda x: Seconds(float(x))args.timeanyargs.timeSecondsadd_argument
class TypedNameSpace(argparse.Namespace):
def __init__(self, *args, **kwargs):
self.time: Seconds = Seconds(0.)
super(TypedNameSpace, self).__init__(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
创建自定义命名空间是正确的方法。您不必为名称指定默认值。只需在类级别键入暗示每个名称就足以让 mypy 在实例级别识别属性的类型:
class TimeNamespace(argparse.Namespace):
time: Seconds
...
args = parser.parse_args(namespace=TimeNamespace())
# mypy reveals type "__main__.Seconds"
reveal_type(args.time)
Run Code Online (Sandbox Code Playgroud)
通过 mypy 的代码演示:https://mypy-play.net/? mypy=latest&python=3.12&gist=4028679c0e89a2c2f609aa2592486e0c
1.成功使用for--time和输出的默认值的代码演示0.016666666666666666:https://ideone.com/8KEGgb