【问题标题】:Keeping alias types simple in Python documentation?在 Python 文档中保持别名类型简单?
【发布时间】:2020-02-02 17:13:37
【问题描述】:

我正在尝试使用 typing 模块来记录我的 Python 包,并且在许多情况下,函数参数允许使用几种不同的类型。例如,您可以传递一个数字、一个 Envelope 对象(我的包中的一个类),或者一个构造 Envelope 的数字列表,或者一个构造信封的数字列表列表。所以我做了一个别名类型如下:

NumberOrEnvelope = Union[Sequence[Real], Sequence[Sequence[Real]], Real, Envelope]

然后我写函数:

def example_function(parameter: NumberOrEnvelope):
    ...

这对我来说看起来很棒。然而,当我使用 Sphinx 创建文档时,我最终得到了这个非常不可读的函数签名:

example_function(参数:Union[Sequence[numbers.Real], Sequence[Sequence[numbers.Real]], numbers.Real, expenvelope.envelope.Envelope])

当我开始尝试在 PyCharm 中使用该函数时弹出的提示也是如此。

有什么方法可以让它保留为“NumberOrEnvelope”。理想情况下,这也会在文档中链接到对“NumberOrEnvelope”是什么的澄清,尽管即使没有,它也会比现在出现的要好得多。

【问题讨论】:

  • example_function 几乎可以肯定是两个或多个独立的函数。至少,example_function_2(parameter: Sequence[Real]) 可以按照example_function_1(parameter: Real) 来实现。
  • 我明白你为什么会这么说,但要更详细一点:它是一个音乐库,其中一个有问题的函数是乐器类的 play_note 方法。它需要三个参数(音高、音量、长度),音高和音量都是这个 NumberOrEnvelope 类型。如果我为音高和音量参数的每种可能组合分别设置函数,我最终会得到相同函数的 9 个副本。我更喜欢具有灵活参数类型的单个函数的简单性。
  • 功能设计对我来说似乎很好。就像大多数 NumPy 函数采用数组一样。想象一下,尝试根据每个参数是否为数组、标量、嵌套序列、具有__array__ 方法的对象、具有__numpy_ufunc__ 方法的对象等来拆分每个 NumPy 函数。
  • 这是我正在尝试做的一个很好的例子。看起来 numpy 的解决方案只是不对该参数进行类型提示,而是将其称为“array_like”。
  • 为什么有这么多方法来指定音高(或音量,或长度)?

标签: python python-sphinx type-hinting type-alias


【解决方案1】:

对此的支持似乎正在进行中。

如果您想尽快修复,可以尝试使用该版本。

【讨论】:

    【解决方案2】:

    编辑:很遗憾,这不太行。

    经过一番搜索后,我找到了我想要的东西。而不是:

    NumberOrEnvelope = Union[Sequence[Real], Sequence[Sequence[Real]], Real, Envelope]
    

    我发现您可以创建自己的复合类型来做同样的事情:

    NumberOrEnvelope = TypeVar("NumberOrEnvelope", Sequence[Real], Sequence[Sequence[Real]], Real, Envelope)
    

    这在文档中显示为“NumberOrEnvelope”,正如我想要的那样。

    【讨论】:

    • 这实际上与别名不同。例如,对于 TypeVar,像 def foo(a: NumberOrEnvelope, b: NumberOrEnvelope): ... 这样的函数现在需要两个参数的类型匹配。你不能通过一个Sequence[Real]和一个Envelope
    • 嗯,这种行为让我觉得非常奇怪。不过,我确实看到 linting 的行为如您所说。为什么要这样设计?
    • TypeVars 不是另一种编写联合的方式(这就是联合的​​用途)。 TypeVar 旨在作为一种编写泛型类和泛型函数的方式。例如,具有append(self, item: T) 方法的泛型类List[T] 要求T 在两种情况下都是相同的类型。同样,一个通用的blah(a: T, b: T) 函数对于整个函数只有一个T
    • 啊,我明白了;很有意义。不过,我想我还是进退两难。我想要一个我描述的类型的联盟,但我不想要丑陋且难以阅读的文档。你有没有想过如何拥有一个不会在文档中打印出这么长时间的工会?
    • 不幸的是,没有。我能想到的最接近的是NewType,但这会改变你调用函数的方式。更好的处理可能需要 Sphinx 增强功能(除非已经有一些我不知道的 Sphinx 选项)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-27
    • 1970-01-01
    • 2022-08-04
    • 1970-01-01
    • 2019-12-09
    • 2019-05-01
    相关资源
    最近更新 更多