这种与isinstance()混合的Python鸭子打字的方法是否有意义?

时间:2013-01-21 08:48:39

标签: python oop duck-typing

假设我们有以下课程:

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没有共同的实现,但是通过构造,它们都将返回True for isinstance(...,Duck)。

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

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

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

2 个答案:

答案 0 :(得分:6)

  

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

我认为你错过了这一点。

当我们谈论“鸭子打字”时,我们真正的意思是没有正式化我们的界面。因此,您尝试做的事情归结为试图回答“我怎样才能使我的界面正式化,同时仍然没有正式化我的界面?”。

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

简而言之,测试isinstance(this_fuzzball_that_was_handed_to_me, Duck)并不是真正有用的事情:

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

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

  • 也许更重要的是,它可能无法通过检查,即使它是一个完全可用的鸭子模糊球。也许它是一些不相关的对象直接有quackwalklook函数,手动作为属性附加到它(而不是它们是它的类的属性,它们在查找时成为方法)。

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

这与EAFP原则有关:不要试图通过观察它来弄清楚某些东西是否是鸭子;弄清楚如果它是一只鸭子,将其视为鸭子,如果不是那么处理血腥的混乱。


但是如果你不关心鸭子的打字理念,并且绝对必须对事物强加一些严谨性,你可能会对标准库abc模块感兴趣。

答案 1 :(得分:1)

即使我不想高估这个词,但是:你的方法不是pythonic。做鸭子打字,或者不做。

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

对于较小的项目,很容易记住您的需求。你可以试试吧。

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

Guido van Rossum谈到了this talk中关于鸭子打字的一些有趣想法。它非常鼓舞人心,值得一看。