我有一个函数需要根据所引用参数的类型而有所不同。我的第一个冲动是包含对isinstance的一些调用,但我一直看到stackoverflow上的答案说这是坏形式和unpythonic但没有很多原因为什么它的不良形式和unpythonic。对于后者,我认为它与鸭子打字有关,但是最重要的是检查你的参数是否属于特定类型?安全玩它不是更好吗?
答案 0 :(得分:3)
我对此事的看法是:
好例子:(这没关系)
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的最高点。你想要多态行为,你不想拼写出类型。
虽然有充分的理由使用它。