zap*_*zap 6 python type-hinting type-variables pyright
考虑以下片段:
from typing import TypeVar
import numpy as np
T = TypeVar("T", float, np.ndarray)
def f(x: T) -> T:
"""
expects a float or an array and returns an output of the same type
"""
return x * 2
f(1) # ok
f(np.array([1, 2, 3])) # ok
def g(x: float | np.ndarray) -> float | np.ndarray:
"""
expects either a float or an array
"""
return f(x) / 2 # should be fine, but pyright complains about type
Run Code Online (Sandbox Code Playgroud)
我创建了一个 TypeVar 来提示f需要输入浮点数或数组,并将返回相同类型的输出。
中的类型提示g更加宽松。它需要一个浮点或一个数组,并将返回一个浮点或一个数组,而不将输出的类型限制为输入的类型。
直观上,这个设置是有道理的。在函数的定义中,g我们知道我们期望x是浮点数或数组,即f期望作为输入的内容。然而,当我转到x最后f一行时,Pyright 抱怨道:
类型“float | ndarray[Unknown, Unknown]”的参数不能分配给函数“f”中类型“T@f”的参数“x”
类型“float | ndarray[Unknown, Unknown]”与约束类型变量“T”不兼容
f这是令人惊讶和令人沮丧的,因为这意味着如果不非常谨慎地编写类型提示的方式,就无法使用我的函数。
关于如何解决这个问题有什么想法吗?
编辑:在 Brian61354270 发表评论后,我重新创建了基本上相同的示例,只是不依赖 numpy。这里我们使用:而不是 numpy 数组Fraction:
from fractions import Fraction
from typing import TypeVar
T = TypeVar("T", float, Fraction)
def f(x: T) -> T:
"""
expects a float or a Fraction and returns an output of the same type
"""
return x * 2
f(1.0) # ok
f(Fraction(1, 2)) # ok
def g(x: float | Fraction) -> float | Fraction:
"""
expects either a float or a Fraction
"""
return f(x) / 2 # should be fine, but pyright complains about type
Run Code Online (Sandbox Code Playgroud)
Pyright 再次报告了本质上相同的问题:
“float | Fraction”类型的参数不能分配给函数“f”中“T@f”类型的参数“x”
类型“float | Fraction”与约束类型变量“T”不兼容
有趣的是,如果我们不Fraction使用int,类型检查就会通过:
from typing import TypeVar
T = TypeVar("T", float, int)
def f(x: T) -> T:
"""
expects a float or an integer and returns an output of the same type
"""
return x * 2
f(1.0) # ok
f(1) # ok
def g(x: float | int) -> float | int:
"""
expects either a float or an integer
"""
return f(x) / 2 # now its ok
Run Code Online (Sandbox Code Playgroud)
虽然不是理想的解决方案,但您可以通过在显式类型保护下重复调用fin来解决此错误:g
def g(x: float | np.ndarray) -> float | np.ndarray:
"""
expects either a float or an array
"""
if isinstance(x, (float, int)):
return f(x) / 2
return f(x) / 2
Run Code Online (Sandbox Code Playgroud)
使用pyright v1.1.329输出:
0 errors, 0 warnings, 0 informations
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
264 次 |
| 最近记录: |