0

我有一个函数,该函数需要根据所接受参数的类型而有所不同。我的第一个冲动是包含一些对 isinstance 的调用,但我一直在 stackoverflow 上看到答案,说这是错误的形式和非 Pythonic 但没有太多理由它的形式不好且不合时宜。对于后者,我想它与鸭式打字有关,但检查你的论点是否属于特定类型有什么大不了的?安全地玩不是更好吗?

4

4 回答 4

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()
于 2013-05-07T13:09:00.380 回答
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。您的函数应该根据类型表现不同的情况存在,但很少见(检查字符串以打开文件是我所知道的更常见的用途之一)。

于 2013-05-07T13:04:24.550 回答
1

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

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

不过,使用它是有正当理由的。

于 2013-05-07T13:08:40.800 回答
1

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

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

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

于 2013-05-07T13:05:46.973 回答