Python 运行时检查复杂变量参数 我们考虑这样的函数: def f(*args, **kwargs): ... @typeguard.typechecked f(*args:Tuple[Any,float,float])

Python 运行时检查复杂变量参数 我们考虑这样的函数: def f(*args, **kwargs): ... @typeguard.typechecked f(*args:Tuple[Any,float,float]),python,arguments,typing,Python,Arguments,Typing,*args是数量可变的参数,必须: (一个对象,一个浮点数,一个浮点数),可能重复N次, 后跟0到N个对象 例如,这是一个有效的调用: f(my_obj, 0, 1, other_obj, 2, 3, obj3, obj4) 但这是无效的: f(my_obj, other_obj, 2, 3) 此函数通过Python shell向用户公开。 所以,检查用户输入是有价值的——我正在使用 使用类型批注的typeguard库 (像mypy) 我正在尝试使用键入模块来编写正确的注释。。。 我想我至少

*args
是数量可变的参数,必须: (一个对象,一个浮点数,一个浮点数),可能重复N次, 后跟0到N个对象

例如,这是一个有效的调用:

f(my_obj, 0, 1, other_obj, 2, 3, obj3, obj4)
但这是无效的:

f(my_obj, other_obj, 2, 3)
此函数通过Python shell向用户公开。 所以,检查用户输入是有价值的——我正在使用 使用类型批注的
typeguard
库 (像mypy)

我正在尝试使用
键入
模块来编写正确的注释。。。
我想我至少可以表达对3个参数组的约束
像这样:

def f(*args, **kwargs):
   ...
@typeguard.typechecked
f(*args:Tuple[Any,float,float])
但它不起作用。 无论如何,我不知道如何在以下对象上添加约束


当然,我可以自己编写一些代码来检查参数,但我确信对于复杂变量参数序列的情况存在更好的方法(或者巧妙地使用
键入
模块,或者另一个Python库?

我所说的验证是什么意思:

def _validate(a, b, c):
    assert isinstance(b, float), f"{b} is not a float!"
    assert isinstance(c, float), f"{c} is not a float"

def _validate_args(args):
  if (len(args) % 3 != 0): # wrong number of args
    raise ValueError("Arguments must be passed in pack of 3")
  for idx in range(0, len(args), 3):
      a, b, c = args[idx: idx + 3]
      _validate(a, b, c)

def func(*args, **kwargs):
  _validate_args(args)

func(1, 2.0, 3, 1, 2, 3)
AssertionError:3不是浮点数


您可以生成任何想要的消息。

当参数与给定类型不匹配时,Python注释不会引发错误。正如您所知,Python是动态类型化的,类型主要是为了可读性。您可以使用
mypy
对代码运行类型检查,但如果您不进行断言,代码本身不会抛出错误。@Nf4r是的,我知道。。。但这是通过shell向用户公开的函数的特殊情况,在运行时进行类型检查很有用。我正在使用typeguard,我更新了我的问题,创建由任何对象组成的接口(a'ka ValueObject)不是更好吗,float和float并表示函数接受这些对象的列表?您可以创建一个自定义类,该类在初始化时处理验证,并在发生错误时抛出错误。这在PEP 484类型提示中是不可能的。基本上,PEP 484假设您的
*arg
**kwarg
参数是同质的——都是相同的类型。如果不是这种情况,您需要将类型保留为
object
,然后自己手动执行检查,或者重新构造代码。例如,我个人会让函数签名更像
f(tups:List[Tuple[Any,float,float]],objs:List[Any])
。写起来可能有点冗长,但将来的读者理解使用此函数的代码可能会容易得多。在3个包之后,您将如何检查其他对象?f(o,1,2,oo,3,4,x,y,z)是否有效取决于您希望通过附加参数实现什么?