14

我的文档很臃肿,因为每当我遇到复杂的鸭子类型时,我都需要某种方式来表达“这种鸭子类型”,但却陷入了“你的函数需要这个输入,但没有'不记录它”,然后记录它。这会导致臃肿、重复的文档,例如:

def Foo(arg):
    """
    Args:
      arg: An object that supports X functionality, and Y functionality,
        and can be passed to Z other functionality.
    """
    # Insert code here.

def Bar(arg):
    """
    Args:
      arg: An object that supports X functionality, and Y functionality,
        and can be passed to Z other functionality.
    """
    # Insert code here.

等等,等等,for BazQux,和其他函数。我需要一些更短的写作方式“arg是一种(对象的类型)”。

对于某些鸭子类型,它就像“类似字典的对象”一样简单:我们知道我们对字典的期望,因此我们知道要传递什么。A dict,或者可以模仿它的东西。

我觉得 C++ 对模板类型也有同样的问题。Haskell 会拥有它,但可以使用类型类的定义来记录它。(注意:Haskell 类!= Java/C++/Python/etc 中的类。)(注意:我并没有真正使用 Haskell 编程,如果这是一个糟糕的例子,请原谅我。)

我应该走传统的 OO 路线,只写一个基类,然后在文档中说“像这个基类这样的东西”吗?代码不会强制从基类派生(因为不需要从基类派生对象),并且基类基本上没有添加任何值,除了记录接口的属性。

另一方面,我正在编写 Python 编程,并且我尝试使用一种语言的习语进行编程。(否则通常会很痛苦。)基类有利于继承功能,但是当您的基类完全抽象时,它似乎不会在鸭子类型语言中增加价值。


编辑:答案:我知道什么是鸭子打字(这应该从帖子中显而易见)。我在哪里记录它是一个问题,尤其是。当不存在附加文档的类时。

4

3 回答 3

8

鸭子类型背后的想法是你记录你期待一只鸭子,并且由其他对象来假装是一只鸭子。

文档中没有任何 API 指定它接受 StringIO 对象;但是,我们可以在大多数需要“类文件对象”的地方使用它们。

此外,在大多数情况下,标准库试图避免命名鸭子类型所需的特定方法。这使得实施可以改变。例如,random.sample API 可以根据迭代或序列来定义。

如果你想比这更具体,你可以使用抽象基类。一些已经包含在集合模块(例如 Iterable、Hashable 和 Sized)或数字模块(Rational、Integral 等)中。模仿那些编写自己的模型并不难。然后,文档只提到需要哪些 ABC(例如xSized IterableyIntegral)。

于 2011-11-09T02:51:51.293 回答
1

鸭式打字的要点是,“类型”的概念变成了一个抽象的直观概念,而不是语言形式上的一部分。与类型检查是语言一部分的语言相比,这使得打字更加流畅和灵活。

使用鸭子类型时需要的不是程序知道您正在使用什么“类型”,而是其他程序员知道。因此,如果您有一整套对特定“类型”对象进行操作的类/函数/等,并且该类型无法用几句话来描述,只需在注释或文档字符串中添加一个部分(甚至一个外部 .txt 文件)描述您的类型并命名它。然后,您可以在任何地方引用该名称。

于 2011-11-09T03:01:30.990 回答
1

更严格的类型语言,如 Java,具有“接口”的概念:任何实现接口的类都应该提供的方法集合。

我想你可以借用这个概念而不必携带严格类型的包袱:只需定义和记录一个抽象类Foo,然后说你的方法需要“a Fooor a Foo-like object”。如果您不想这样做,您甚至不必让任何其他类实际继承Foo;阅读文档的人仍然会知道去哪里找出对Foo-like 对象的期望。

于 2011-11-09T03:05:21.677 回答