PyCharm 表示未填充的参数,即使所有参数都是可选的

Posted

技术标签:

【中文标题】PyCharm 表示未填充的参数,即使所有参数都是可选的【英文标题】:PyCharm says unfilled parameters even though all parameters are optional 【发布时间】:2021-11-23 05:34:27 【问题描述】:

我有一个函数应该接收另一个函数作为参数。我将该参数注释定义为:

input_function: Callable[
    [
        Optional[InputType],
        Optional[Sequence[str]],
        Optional[bool]
    ],
    Awaitable[str]
] = func

与此同时,我的 func 函数是这样定义的:


async def func(input_type: InputType = None, formats: Sequence[str] = (), *, hide: bool = False) -> str: ...

函数签名和参数注解应该相同。但是,当我只用一个参数调用该函数时(因为所有参数都是可选的),PyCharm 说有未填充的参数:

【问题讨论】:

【参考方案1】:

TLDR:将签名定义为带有__call__Protocol,而不是Callable

from typing import Protocol


class InputFunction(Protocol):
    async def __call__(self, input_type: InputType = None, formats: Sequence[str] = (), *, hide: bool = False) -> str: ...

input_function: InputFunction = func

Callable 类型只能表达一种有限的签名:显式位置参数,例如 Callable[[A, B], R] 或任意参数,例如 Callable[..., R]。将其参数之一键入为Optional[T] 意味着它必须是“a TNone”,而不是可以省略。

相比之下,Protocol__call__ 方法允许使用常规定义语法定义签名,包括其所有功能,例如默认值。

Callback Protocols

协议可用于定义使用Callable[...] 语法难以(甚至不可能)表达的灵活回调类型,例如可变参数、重载和复杂的泛型回调。它们是用一个特殊的__call__ 成员定义的:

虽然Protocol 是一个类,但它在结构上匹配:仅使用__call__ 方法定义它只是编码“具有相同签名的可调用对象”,并且具有相同签名的函数也满足这一点。

注意self 参数在__call__ 定义中是必需的,但不用于检查签名是否匹配。

【讨论】:

您似乎实现了func 而不是__call__。这是一个错误还是应该是这样的? @Jonathan1609 哎呀。那确实是一个错误。固定。 好吧,我一到电脑就会标记这个答案。谢谢! 这不起作用,因为我不希望 PyCharm 告诉最终用户他的函数应该是 InputFunction 的一个实例。我希望 Pycharm 告诉他使用适合 __call__ 中签名的函数。照片:imgur.com/p969BRC.png 你能看看它,看看有什么问题吗?【参考方案2】:

The documentation for typing.Optional 状态:

请注意,这与可选参数的概念不同,可选参数具有默认值。

the documentation for typing.Callable 表示:

没有指示可选或关键字参数的语法

因此,无法按照您想要的方式准确定义函数的类型。

【讨论】:

你的第一点是正确的,你的第二点是不正确的。您正确地指出 typing.Optional 并不意味着 OP 似乎认为它确实如此,这是非常有用的信息。不幸的是,您的第二点是不正确的——可以准确定义指示可选或关键字参数的函数。做到这一点的方法是使用回调协议,正如@MisterMiyagi 在他的回答中所说的那样,正如 MyPy 文档 mypy.readthedocs.io/en/stable/protocols.html#callback-protocols 所建议的那样

以上是关于PyCharm 表示未填充的参数,即使所有参数都是可选的的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio(s-s-rS)中未填充相关参数

使用条件断点进行 IntelliJ/PyCharm 调试:未定义函数参数

Django - 自定义装饰器 - 参数未填充

参数未从 Ajax 调用填充(尝试了一切)

pycharm里怎样选中多行集体空格后移

jQuery Ajax 帖子未传递参数