python - 从另一个泛型 lambda 的参数推断泛型 lambda 参数
问题描述
考虑以下代码:
from typing import Callable, TypeVar
T = TypeVar('T')
def middle_man(
producer: Callable[[], T],
consumer: Callable[[T], None]
) -> None:
consumer(producer())
middle_man(
lambda: "HELLO",
lambda s: print(s.lower())
)
此代码运行没有错误并且按预期工作,但是,mypy 无法推断s
第二个 lambda 中的类型,给出错误:
“object”没有属性“lower”`
现在,我唯一的解决方法是 cast s
,这在更复杂的 lambda 或更复杂的类型中可能会很痛苦,或者 add # type: ignore
,我不想这样做。
有没有更好的解决方法,或者让 mypy 识别类型的正确方法?
解决方案
在我看来,您在这里有两个相互矛盾的问题:
- 你希望你
T
TypeVar
是通用的,以便producer
和consumer
参数的类型注释middle_man
可以灵活 - 您希望特定调用的类型注释
middle_man
足够具体,以mypy
识别您正在使用str
类型调用它
为了实现这一点,我将middle_man
通过首先将参数存储为变量来注释特定调用的参数:
from typing import Callable, TypeVar
T = TypeVar('T')
def middle_man(
producer: Callable[[], T],
consumer: Callable[[T], None]
) -> None:
consumer(producer())
producer: Callable[[], str] = lambda: "HELLO"
consumer: Callable[[str], None] = lambda s: print(s.lower())
middle_man(producer, consumer)
编辑
另一个建议:
由于无论如何您都在使用泛型TypeVar
,因此您可以将其替换为Any
类型而不会丢失类型信息,并且mypy
不会引发错误,因为它会跳过对types的静态类型检查Any
。
from typing import Callable, Any
def middle_man(
producer: Callable[[], Any],
consumer: Callable[[Any], None]
) -> None:
consumer(producer())
middle_man(
lambda: "HELLO",
lambda s: print(s.lower())
)
我知道这个解决方案不是很令人满意,因为它基本上违背了mypy
用于静态类型检查的目的,但除非你想用一个方法将你的上限限制TypeVar
为一个类,lower
否则这可能是你最好的选择。
推荐阅读
- node.js - Socket.io:连接到 Heroku 上的套接字服务器时找不到 404
- windows - 如何压缩文件名中包含今天日期的文件夹?
- swift - UITextField 下划线宽度问题
- wpf - 值不为 Null 的数据触发器
- c# - 为什么 MailKit SmtpClient.Send() 失败时我没有收到异常?
- sql - QTODBC 中的变量到 Oracle
- rest - grails 3.3.9 - 从 restfulController 扩展失败并显示“未找到默认构造函数”
- objective-c - 如何从另一个插件调用cordova插件(本机iOS)方法?
- java - 如何使用listFilesAndDirs只获取目录而不递归操作
- testing - 我可以使用单个 Zephyr 测试用例来维护多个设备上的测试执行记录吗?