mypy无法识别copy.copy和copy.deepcopy可调用性的问题
问题原因
copy函数的类型签名特性:copy.copy和copy.deepcopy的类型定义包含可选参数(比如deepcopy的memo和_nil参数),mypy会保留完整的函数签名。当你把它们赋值给变量后,变量类型是带多参数的Callable,而map要求的是仅接受单个参数的函数,类型不匹配导致报错。- 条件赋值的类型推断限制:用
x if y else z把两个copy函数赋值给变量时,mypy无法自动推断出两者的最小共同类型,只能将变量类型标记为function(未知可调用类型),调用时就会提示“无法调用未知类型的函数”。 map调用的严格类型检查:直接调用map(copy.deepcopy, ...)时,deepcopy的签名是Callable[[_T, Optional[Dict[int, Any]], Any], _T],而map期望的是Callable[[int], _T],参数数量不匹配触发类型错误。但列表推导直接调用时,mypy会根据上下文判断你只传了一个参数,所以能通过检查。
解决办法
1. 显式标注变量类型(推荐)
给赋值的变量指定明确的单参数Callable类型,帮mypy缩小类型范围:
from typing import Callable, TypeVar import copy _T = TypeVar("_T") do_deepcopy = True # 标注为仅接受一个参数的泛型Callable copyfct: Callable[[_T], _T] = copy.deepcopy if do_deepcopy else copy.copy numbers = [2, 3, 4] list(map(copyfct, numbers)) # 类型检查通过 [copyfct(i) for i in numbers] # 类型检查通过
如果针对特定类型(比如int),也可以写Callable[[int], int],泛型写法更通用。
2. 包装函数屏蔽可选参数
写一个简单的包装函数,只传递必要参数,让mypy看到的是单参数函数:
import copy def my_copy(obj): return copy.copy(obj) def my_deepcopy(obj): return copy.deepcopy(obj) do_deepcopy = True copyfct = my_deepcopy if do_deepcopy else my_copy numbers = [2, 3, 4] list(map(copyfct, numbers)) # 正常通过检查 [copyfct(i) for i in numbers] # 正常通过检查
这种方式不需要额外类型注解,mypy能自动推断包装函数的类型。
3. 临时跳过类型检查(不推荐,仅应急)
如果不想修改代码结构,可以用# type: ignore注释跳过mypy的检查,但会丢失类型安全:
list(map(copy.deepcopy, numbers)) # type: ignore
4. 升级mypy版本
你使用的mypy 1.1.1版本较旧,后续版本对标准库的类型注解支持更完善,可能已经修复了这类推断问题。可以尝试升级:
pip install --upgrade mypy
内容的提问来源于stack exchange,提问作者VY_CMa
相关产品推荐
相关产品推荐

