gpt4 book ai didi

python - 对 ParamSpec 变量应用转换?

转载 作者:行者123 更新时间:2023-12-05 03:27:50 25 4
gpt4 key购买 nike

我有什么方法可以在 ParamSpec 上应用转换?我可以用一个例子来说明这个问题:

from typing import Callable

def as_upper(x: str):
return x.upper()

def eventually(f: Callable[P, None], *args: P.args, **kwargs: P.kwargs):
def inner():
def transform(a):
return a() if isinstance(a, Callable) else a
targs = tuple(transform(a) for a in args)
tkwargs = {k: transform(v) for k,v in kwargs.items()}
return f(*targs, **tkwargs)
return inner

eventually(as_upper, lambda: "hello") # type checker complains here

这个类型检查器(在我的例子中是 pyright)会提示这个。函数 最终 收到可调用的 () -> str 而不是预期的 str 。我的问题是:有什么方法可以让我指定它应该期望 () -> str 而不是 str 本身?通常,如果一个函数需要类型 T,我可以将其转换为(比如)() -> T?

我基本上是在询问是否有可能以某种方式转换 ParamSpec,以便相关函数不需要相同的参数,而是“几乎”相同的参数。

我真的不希望这是可能的,但也许有更多类型检查经验的人知道这个问题的潜在解决方案。 :)

最佳答案

当前可用的工具 (Python 3.10) 无法正确输入此装饰器。

这里有两个主要问题:

  • ParamSpecConcatenate 目前只允许我们修改固定数量的参数。
  • 我们不能连接只有关键字的参数(这使得转换 **kwargs: P.kwargs 不可能)

然而,在这些约束下,如果位置参数已知,我们可以利用柯里化(Currying)实现一个不太优雅的解决方案:

from typing import Callable, Concatenate, ParamSpec, TypeVar

T = TypeVar("T")
RetT = TypeVar("RetT")
P = ParamSpec("P")

def something(a: str, b: int, c: bool):
return f"{a} {b} {c}"

def eventually(
f: Callable[Concatenate[T, P], RetT], a: Callable[[], T]
) -> Callable[P, RetT]:
def inner(*args: P.args, **kwargs: P.kwargs) -> RetT:
transformed = a() if callable(a) else a
return f(transformed, *args, **kwargs)

return inner


something_eventually = eventually(
eventually(eventually(something, lambda: "hello"), lambda: 2), lambda: False
)
something_eventually() # hello 2 False

请注意,目前还无法连接关键字参数 ( See also )。

eventually 也可以以更函数化的方式应用(但不能正确输入):

from functools import reduce

# Though it unfortunately doesn't type check
something_eventually = reduce(
eventually,
[lambda: "hello", lambda: 2, lambda: False],
something,
)
something_eventually() # hello 2 False

reduce 期望值的类型具有相同的类型,而我们在每次迭代中更改函数的类型。当我们以这种方式最终任意次应用时,这使得无法键入它。

reduce 只是一个例子。从更一般的意义上说,我怀疑我们是否可以正确地键入一些涉及重复应用柯里化(Currying)函数的东西,例如上面提出的 eventually,至少在当前的 Concatenate 支持下。

关于python - 对 ParamSpec 变量应用转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71362488/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com