不理解类型检查的不良形式 - 鸭子打字

时间:2013-05-07 12:58:34

标签: python python-2.7 typechecking

我有一个函数需要根据所引用参数的类型而有所不同。我的第一个冲动是包含对isinstance的一些调用,但我一直看到stackoverflow上的答案说这是坏形式和unpythonic但没有很多原因为什么它的不良形式和unpythonic。对于后者,我认为它与鸭子打字有关,但是最重要的是检查你的参数是否属于特定类型?安全玩它不是更好吗?

4 个答案:

答案 0 :(得分:3)

咨询this great post


我对此事的看法是:

  • 如果您要限制代码,请不要这样做。
  • 如果您使用它来指导您的代码,请将其限制为非常具体的情况。

好例子:(这没关系)

def write_to_file(var, content, close=True):
    if isinstance(var, str):
        var = open(var, 'w')
    var.write(content)
    if close:
        var.close()

错误示例:(这很糟糕)

def write_to_file(var, content, close=True):
    if not isinstance(var, file):
        raise Exception('expected a file')
    var.write(content)
    if close:
        var.close()

答案 1 :(得分:1)

使用isinstance限制可以传递给函数的对象。例如:

def add(a,b):
    if isinstance(a,int) and isinstance(b,int):
        return a + b
    else:
        raise ValueError

现在您可以尝试调用它:

add(1.0,2)

期望获得3,但是您会收到错误,因为1.0不是整数。很明显,在这里使用isinstance会阻止我们的功能尽可能地有用。最终,如果我们的对象在烤制时会像鸭子一样味道,那么只要它们起作用,我们就不在乎它们的类型。

但是,有些情况恰恰相反:

def read(f):
    if isinstance(f,basestring):
        with open(f) as fin
            return fin.read()
    else:
        return f.read()

关键是,您需要确定您希望函数具有的API。根据类型存在您的函数应该有不同行为的情况,但很少见(检查字符串打开文件是我所知道的更常见的用途之一)。

答案 2 :(得分:1)

因为这样做明确地防止了鸭子打字。

这是一个例子。 csv模块允许我以CSV格式将数据写入文件。因此,该函数接受一个文件作为参数。但是,如果我不想写入实际文件,而是写入StringIO对象之类的内容呢?这是一个非常好用的,因为StringIO实现了必要的读写方法。但是如果csv明确检查类型为file的实际对象,那将被禁止。

一般来说,Python认为我们应该尽可能地允许事情 - 这与在类中缺少真正的私有变量背后的原因相同。

答案 3 :(得分:1)

有时使用isinstance只是重新实现多态分派。查看str(...),它会调用object.__str__(..),它是针对每种类型单独实现的。通过实施__str__,您可以通过扩展该对象而不必操纵内置方法str来重用依赖于str(...)的代码。

基本上这是OOP的最高点。你想要多态行为,你不想拼写出类型。

虽然有充分的理由使用它。