使用类型提示来区分坐标系使用numpy的方式

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

Way to use typehints to distinguish coordinate frames using numpy

问题

我正在开发一个处理不同坐标系的Python库。由于混淆的坐标系给我带来了一些问题,我想要在我的代码中更加有序。为此,我想要为坐标分配类型提示,并使用Mypy来检查它们。我的当前方法是

from typing import NewType, cast
import numpy as np
import numpy.typing as npt

frameA = NewType('frameA', npt.NDArray)
frameB = NewType('frameB', npt.NDArray)

def f(x_A : frameA) -> frameB:
    # 做一些从frame A到frame B的操作
    x_B = - x_A
    return cast(frameB, x_B)

# 应该工作
x_A : frameA = np.random.rand(3,2)
x_B = f(x_A)

# 应该引发错误
x_B : frameB = np.random.rand(3,2)
x_A = f(x_B)

确实,Mypy能够检测到f的输入是否在正确的坐标系中。然而,让我困扰的是,定义x_A : frameA = np.random.rand(3,2)也会引发错误,因为np.random.rand(3,2)的类型是ndarray[Any, dtype[floating[_64Bit]]],为了将其转换为frameA,我必须进行类型转换。

是否有更好的方法来做到这一点,而不需要每次生成新变量时都进行类型转换?例如,有没有办法像这样做会更好:

x_A : frameA = np.random.rand((3,2), type=frameA)


<details>
<summary>英文:</summary>

I&#39;m working on a python library dealing with coordinates in different frames. As I had quite some issues with confused frames, I&#39;d like to bring more order into my code. 

For this purpose, I want to assign typehints to coordinates and use Mypy to check them. My current approach is


from typing import NewType, cast
import numpy as np
import numpy.typing as npt

frameA = NewType('frameA', npt.NDArray)
frameB = NewType('frameB', npt.NDArray)

def f(x_A : frameA) -> frameB:
# do something to get from frame A to frameB
x_B = - x_A
return cast(frameB, x_B)

should work

x_A : frameA = np.random.rand(3,2)
x_B = f(x_A)

should throw error

x_B : frameB = np.random.rand(3,2)
x_A = f(x_B)


Indeed, Mypy is able to detect if the input of `f` is in the correct coordinate frame. What bothers my however, is that the definition `x_A : frameA = np.random.rand(3,2)` throws an error as well, because `np.random.rand(3,2)` is of type `ndarray[Any, dtype[floating[_64Bit]]]` and to make it `frameA`, I have to cast it.

Is there any nicer way to do this without the need of casting the variables every time I generate new ones? F.e., It would be really nice to have something like

x_A : frameA = np.random.rand((3,2), type=frameA)


</details>


# 答案1
**得分**: 2

`frameA`不仅仅是`NDArray`的别名;它是一个完全不同的类型,其值是从`NDArray`类型的值中*创建的*(尽管是微不足道的\*)。

你需要写

    x_A : frameA = frameA(np.random.rand(3,2))

与其他类型的组合一样,Python不会仅仅因为可以将`np.random.rand(3, 2)`返回的值转换成`frame`类型的值而隐式地进行转换或构建。

---
\* 在运行时,`frameA`实际上只是简单地返回其参数的值,因此从这个意义上说,`frameA`和`NDArray`值共享相同的运行时表示。

<details>
<summary>英文:</summary>

`frameA` is not just an alias for `NDArray`; it is an entirely distinct type whose values are *created from* (albeit trivially\*) values of type `NDArray`.

You need to write

    x_A : frameA = frameA(np.random.rand(3,2))

Like any other combinations of types, Python will not simply cast or otherwise construct a value of type `frame` implicitly just because it&#39;s *possible* to convert the value returned by `np.random.rand(3, 2)`.

---
\* At runtime, `frameA` really does simply return the value of its argument unchanged, so in that sense `frameA` and `NDArray` values share the same runtime representation.

</details>



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

发表评论

匿名网友

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

确定