2013-05-07 26 views
0

我有一个函数,需要根据参数的类型采取不同的行为。我的第一个冲动是包含一些对isinstance的调用,但我不断看到答案stackoverflow说,这是不好的形式和unpythonic,但没有太多的理由为什么它的不良形式和unpythonic。对于后者,我想这与鸭子打字有关,但最重要的是要检查你的论点是否属于特定类型?玩安全不是更好吗?不理解类型检查的错误形式 - 鸭子打字

+0

所以你的问题是,什么是鸭打字的目的是什么? – jamylak 2013-05-07 13:02:20

+0

我想回答这将有助于澄清我的误解。 – 2013-05-07 13:03:33

+1

请参阅[鸭子打字](http://en.wikipedia.org/wiki/Duck_typing)以获取更多信息并与其他类型系统进行比较。 – martineau 2013-05-07 13:29:53

回答

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。你的函数应该根据类型行为不同的情况存在,但很少见(检查字符串以打开文件是我所知道的更常见的用法之一)。

1

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

下面是一个例子。 csv模块允许我以CSV格式将数据写入文件。出于这个原因,该函数接受一个文件作为参数。但是如果我不想写一个实际的文件,而是想写一个像StringIO对象的东西呢?这是一个很好的使用它,因为StringIO实现必要的读写方法。但是如果csv明确地检查了file类型的实际对象,那将是被禁止的。

通常,Python认为我们应该尽可能地允许事物 - 这与在类中缺少真正的私有变量背后的原因是一样的。

1

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

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

虽然有正当理由使用它。

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

谢谢!那篇文章确实很棒。 – 2013-05-07 13:15:19