Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python3键入varadic“;套用;样式定义_Python_Python 3.x_Types_Typing_Python Typing - Fatal编程技术网

Python3键入varadic“;套用;样式定义

Python3键入varadic“;套用;样式定义,python,python-3.x,types,typing,python-typing,Python,Python 3.x,Types,Typing,Python Typing,我一直在努力编写类型定义 例如,将类型指定给: def foo(fn, *args): return fn(*args) 我能做的最好的事情就是使用: 哪种方法最适合做正确的事情…例如: def bar(i: int, j: int) -> None: print(i) 以下是成功的例子: foo(bar, 10, 12) 尽管这些措施失败了: foo(bar, 10) foo(bar, 10, 'a') foo(bar, 10, 12) + 1 但是如果我用myp

我一直在努力编写类型定义

例如,将类型指定给:

def foo(fn, *args):
    return fn(*args)
我能做的最好的事情就是使用:

哪种方法最适合做正确的事情…例如:

def bar(i: int, j: int) -> None:
    print(i)
以下是成功的例子:

foo(bar, 10, 12)
尽管这些措施失败了:

foo(bar, 10)
foo(bar, 10, 'a')
foo(bar, 10, 12) + 1
但是如果我用mypy--strict检查,我会得到:

test.py:15: error: Function is missing a type annotation
test.py:15: error: Overloaded function implementation does not accept all possible arguments of signature 1
test.py:15: error: Overloaded function implementation does not accept all possible arguments of signature 2
test.py:15: error: Overloaded function implementation does not accept all possible arguments of signature 3
(也就是说最终的
foo
定义本身没有任何类型)

我可以将
foo
重新定义为:

def foo(fn: Callable[..., R], *args: Any) -> R:
    return fn(*args)
但是当我运行
mypy--strict
时,我得到:

test.py:15: error: Function is missing a type annotation
test.py:15: error: Overloaded function implementation does not accept all possible arguments of signature 1
test.py:15: error: Overloaded function implementation does not accept all possible arguments of signature 2
test.py:15: error: Overloaded function implementation does not accept all possible arguments of signature 3
我真的不明白


如果有人能提出一种更好的方法来为这种函数赋予类型,我们将不胜感激!如果我也能做到这一点,而不列出大量的
重载
s,那就好了,真正的定义也有一些“仅关键字”参数,这样就好了,不必每次重复

这就是为什么“重载函数实现不接受所有可能的参数…”错误是因为重载实现无法正确处理如下所示的调用:
foo(my_callable,a=3,b=4)

毕竟,根据您的重载签名,理论上用户可以显式地为a、b、c等使用命名参数——因此,您的实现需要支持这些类型的调用

有两种不同的方法可以解决此问题

第一种方法是附加一个
**kwargs:Any
,并修改重载实现,使其如下所示:

def foo(fn: Callable[..., R], *args: Any, **kwargs: Any) -> Any:
    return fn(*args, **kwargs)
现在,您的实现将正确处理这些类型的调用

第二种方法是在每个参数前面加两个下划线,如下所示:

@overload
def foo(fn: Callable[[A], R], __a: A) -> R: ...
@overload
def foo(fn: Callable[[A, B], R], __a: A, __b: B) -> R: ...
@overload
def foo(fn: Callable[[A, B, C], R], __a: A, __b: B, __c: C) -> R: ...

def foo(fn: Callable[..., R], *args: Any) -> Any:
    return fn(*args)
当mypy看到一个以两个下划线开头的参数时,它理解该参数仅用于位置。因此,mypy将拒绝像
foo(my\u fn,\u a=3,\u\u b=4)
这样的调用

但这是唯一的打字方式。在参数前面加两个下划线在运行时没有特殊意义


关于不必重复这么多重载的更广泛的问题:不幸的是,现在我们能做的最好的事情就是附加一堆重载。您使用的技术与typeshed用于键入函数的技术相同,例如
map(…)
filter(…)


为了做得更好,我们需要一个叫做变量泛型的特性——但它们是一个复杂的特性,不幸的是mypy还不支持它们。该计划有望在2019年晚些时候实施,这样您就可以删除重载了。

也许这是相关的:。我还认为,如果您使用第二个版本的
foo
definition而不重载,它将正常工作,并且可以接受您的所有组合。@MehdiSadeghi感谢您的回复,但我不明白!当你说“没有重载”时,我想你的意思是我应该删除
@重载
修饰的定义?如果是这样的话,它怎么知道
foo(bar,10,'a')
是不正确的呢?谢谢你的明确解释!我试图找到类似的例子来看看其他人是怎么做的,但没有找到任何东西,typeshed看起来像是我应该找的地方…我在其他语言中看到/使用了类似的“多重重载”技巧(例如C++中的模板),因此在这里使用它,有趣的是听到正在考虑替代方案