Pylance 中 Union 类型变量的类型推断问题

huangapple go评论164阅读模式
英文:

Type inference issue in Pylance for a variable of Union type

问题

我正在编写一个根据参数是标量还是NumPy数组而具有不同行为的函数。然而,我遇到了以下两个类型错误,我不知道如何解决:

  1. 表达式类型为"generic | bool | int | float | complex | str | bytes | memoryview"不能赋值给返回类型"float"。
    类型"generic | bool | int | float | complex | str | bytes | memoryview"不能赋值给类型"float"。
    "bytes"与"float"不兼容。Pylance报告一般类型问题。

  2. 类型"float"上未定义"getitem"方法。Pylance报告一般类型问题。

我该如何让Pylance知道,如果代码达到if语句内的表达式,x应该是一个float,如果达到else表达式,x应该是一个NumPy数组?

示例代码:

import numpy as np
import numpy.typing as npt

def func(x: float | npt.NDArray[np.float64]) -> float:
    if np.isscalar(x):
        return x     # 错误1)
    else:
        return x[0]  # 错误2)

def main():
    x = 0.4
    print(func(x))

if __name__ == "__main__":
    main()
英文:

I'm writing a function with different behaviors depending on whether the argument is a scalar or a NumPy array. However, I'm getting the following two typing errors that I don't know how to solve:

  1. Expression of type "generic | bool | int | float | complex | str | bytes | memoryview" cannot be assigned to return type "float"
    Type "generic | bool | int | float | complex | str | bytes | memoryview" cannot be assigned to type "float"
    "bytes" is incompatible with "float"
    PylancereportGeneralTypeIssues
  2. "__ getitem __" method not defined on type "float" PylancereportGeneralTypeIssues**.

How can I let Pylance know that if the code reaches the expressions inside the if statement x should be a float, and if it reaches the else expresssions x should be a NumPy array?

Example code:

import numpy as np
import numpy.typing as npt


def func(x: float | npt.NDArray[np.float64]) -> float:
    if np.isscalar(x):
        return x     # Error 1)
    else:
        return x[0]  # Error 2)


def main():
    x = 0.4
    print(func(x))


if __name__ == "__main__":
    main()

答案1

得分: 1

一种可能性是添加一个assertcast来强制将其视为浮点数。以下任何一种方法都可以工作:

assert isinstance(x, float)
x = cast(float, x)
x = float(x)  # type: ignore

总之:

def func(x: float | npt.NDArray[np.float64]) -> float:
    if np.isscalar(x):
        assert isinstance(x, float)
        return x
    else:
        assert not isinstance(x, float)
        return x[0]

...虽然更直接的方式可能是:

def func(x: float | npt.NDArray[np.float64]) -> float:
    return x if isinstance(x, float) else x[0]

...除非您依赖于np.isscalar执行与这些类型签名所建议的不同的操作。

英文:

One possibility is to add an assert or a cast to force it to be treated as a float. Any of the following will work:

assert isinstance(x, float)
x = cast(float, x)
x = float(x)  # type: ignore

All together:

def func(x: float | npt.NDArray[np.float64]) -> float:
    if np.isscalar(x):
        assert isinstance(x, float)
        return x
    else:
        assert not isinstance(x, float)
        return x[0]

...although, more direct would have been:

def func(x: float | npt.NDArray[np.float64]) -> float:
    return x if isinstance(x, float) else x[0]

...unless you're relying upon np.isscalar to do something other than what these type signatures suggest.

huangapple
  • 本文由 发表于 2023年6月19日 14:26:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76504096.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定