1

假设我们有以下类:

class Duck(object):
    pass

class OldFashionedDuck(Organism, Duck):
    def look(self):
        self.display_biological_appearance()
    def walk(self):
        self.keep_balance_on_two_feet()
    def quack(self):
        self.make_noise_with_lungs("Quack!")

class ArtificialDuck(Robot, Duck):
    def look(self):
        self.display_imitation_biological_appearance()
    def walk(self):
        self.engage_leg_clockwork()
    def quack(self):
        self.play_sound("quack.au")

在这个例子中,OldFashionedDuck 和ArtificialDuck 没有共同的实现,但是通过构造它们都将为isinstance(..., Duck) 返回True。

这并不完美,但我认为这可能有助于尊重鸭子类型,并且(通过空的 mixin 继承)允许 isinstance()。本质上,它提供了一个满足接口的契约,因此它并不是真正基于完成所有工作的类调用 isinstance(),而是基于任何人都可以选择加入的接口。

我看过基于“isinstance() 被认为有害”的文章,因为它破坏了鸭子类型。但是,我至少作为一名程序员想知道,如果不一定是对象从哪里获取函数,而是它是否实现了接口。

这种方法有用吗?如果有用,可以改进吗?

4

2 回答 2

6

我看过基于“isinstance() 被认为有害”的文章,因为它破坏了鸭子类型。但是,我至少作为一名程序员想知道,如果不一定是对象从哪里获取函数,而是它是否实现了接口。

我认为你没有抓住重点。

当我们谈论“duck typing”时,我们真正的意思不是形式化我们的接口。因此,您要尝试做的事情归结为尝试回答“如何在仍然不使界面形式化的情况下形式化我的界面?”的问题。

我们期望给我们一个对象来实现一个接口——我们描述的一个接口,不是通过创建一个基类,而是通过编写一堆文档和描述行为(如果我们感觉特别活泼,设置某种测试套件) - 因为我们说过这是我们所期望的(再次在我们的文档中)。我们通过尝试像使用它一样使用它来验证对象是否实现了接口,并将任何产生的错误视为调用者的责任。调用给我们错误对象的代码是很顽皮的,这就是需要修复错误的地方。(同样,测试帮助我们追踪这些事情。)

简而言之,测试isinstance(this_fuzzball_that_was_handed_to_me, Duck)并没有真正的帮助:

  • 它可以通过isinstance检查,但以违反我们期望(或者说,return NotImplemented)的方式实现这些方法。只有真正的测试才会在这里进行。

  • 它可以通过检查,但实际上完全没有实现一个或多个方法;毕竟,基础Duck不包含任何实现,Python 没有理由在派生类中检查它们。

  • 也许更重要的是,它可能无法通过检查,即使它是一个完全可以像鸭子一样使用的绒毛球。也许它是一些不相关的对象,它quack直接walk作为look属性手动附加到它(而不是它们是它的类的属性,当查找时它们成为方法)。

好的,所以,“不要那样做”,你说。但是现在你正在为每个人做更多的工作;如果客户并不总是选择加入,那么使用鸭子的代码进行检查是无用且危险的。同时,你得到了什么?

这与 EAFP 原则有关:不要试图通过看某物来判断它是否是 Duck;通过将其视为鸭子并处理血淋淋的烂摊子来确定它是否是鸭子。


但是,如果您不关心鸭子类型的哲学,并且绝对必须对事物施加一些严格的外表,那么您可能会对标准库abc模块感兴趣。

于 2013-01-21T09:08:59.980 回答
1

尽管我不想高估这个术语,但是:你的方法不是 pythonic。做鸭子打字,或者不做。

如果您想确保您的“接口”实现实现了它应该实现的一切:测试它!

对于较小的项目,很容易记住您需要什么。你可以简单地尝试一下。

我同意对于较大的项目,甚至团队合作,最好确保您的类型拥有所需的一切。在这种情况下,您绝对应该使用单元测试来确保您的类型是完整的。即使没有鸭式打字,您也需要测试,因此您可能不需要任何额外的测试。

Guido van Rossum 在本次演讲中谈到了一些关于鸭式打字的有趣想法。它是如此鼓舞人心,绝对值得一看。

于 2013-01-21T09:17:44.540 回答