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

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

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数组?

示例代码:

  1. import numpy as np
  2. import numpy.typing as npt
  3. def func(x: float | npt.NDArray[np.float64]) -> float:
  4. if np.isscalar(x):
  5. return x # 错误1)
  6. else:
  7. return x[0] # 错误2)
  8. def main():
  9. x = 0.4
  10. print(func(x))
  11. if __name__ == "__main__":
  12. 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:

  1. import numpy as np
  2. import numpy.typing as npt
  3. def func(x: float | npt.NDArray[np.float64]) -> float:
  4. if np.isscalar(x):
  5. return x # Error 1)
  6. else:
  7. return x[0] # Error 2)
  8. def main():
  9. x = 0.4
  10. print(func(x))
  11. if __name__ == "__main__":
  12. main()

答案1

得分: 1

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

  1. assert isinstance(x, float)
  2. x = cast(float, x)
  3. x = float(x) # type: ignore

总之:

  1. def func(x: float | npt.NDArray[np.float64]) -> float:
  2. if np.isscalar(x):
  3. assert isinstance(x, float)
  4. return x
  5. else:
  6. assert not isinstance(x, float)
  7. return x[0]

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

  1. def func(x: float | npt.NDArray[np.float64]) -> float:
  2. 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:

  1. assert isinstance(x, float)
  2. x = cast(float, x)
  3. x = float(x) # type: ignore

All together:

  1. def func(x: float | npt.NDArray[np.float64]) -> float:
  2. if np.isscalar(x):
  3. assert isinstance(x, float)
  4. return x
  5. else:
  6. assert not isinstance(x, float)
  7. return x[0]

...although, more direct would have been:

  1. def func(x: float | npt.NDArray[np.float64]) -> float:
  2. 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:

确定