如何正确合并duck-typing以返回原始类型?

时间:2012-07-10 21:03:21

标签: python numpy duck-typing

我真的希望这不是重复。我试图搜索我的问题,但我似乎无法找到它。

所以我有一个相当简单的功能,可以将脚转换为米:

def feetToMeters(val):
    return numpy.array(val) * 0.3048

这很好用,并接受整数,浮点数,数组和列表。但是,如果我放入一个列表(而不是一个numpy数组),我想要返回一个列表。所以我写了这个:

def feetToMeters(val):
    try:
        return val * 0.3084
    except TypeError:
        return [0.3084 * v for v in val]

(或者我可以使用return list(numpy.array(val) * 0.3084)作为最后一行,如果我想在这里使用numpy,我不知道这是否真的重要。)

这是在这里加入duck-typing的最佳方法,这样我就可以避免使用type函数了吗?最初我试过AttributeError,但它没有用。尽管如此,我仍对TypeError感到厌倦,尽管它似乎有效。

使用if type(val) is list代替是否是亵渎神灵?

4 个答案:

答案 0 :(得分:6)

  

使用if type(val) is list代替是否是亵渎神灵?

是的,因为它不适用于列表的子类。如果你想这样,至少做isinstance(val, list)。这是一个专门处理列表的解决方案,并将其他所有内容(包括标量和元组)转换为NumPy数组:

def feetToMeters(feet):
    meters = np.asarray(feet) * 0.3048
    return list(meters) if isinstance(feet, list) else meters

请注意:

  • 传递list子类的实例将导致返回普通list;
  • 传递列表列表将导致返回NumPy数组列表。

您可以对此进行扩展以特别处理更多类型,但通常,对于要处理的每种类型,您需要编写更多代码,因为您需要知道如何构造该类型。因此,这种类型转换通常留给客户端代码。

答案 1 :(得分:3)

由于你已经使用了numpy,我会避免在这里使用像

这样的例外
def feetToMeters(val):
    if numpy.isscalar(val):
        return val * 0.3084
    else:
        return numpy.array(val) * 0.3048

答案 2 :(得分:1)

捕获TypeError很危险,因为它可能是由列表以外的很多东西引起的。我通常会为此目的使用isinstance(val,list)。

答案 3 :(得分:0)

诀窍是你正在尝试支持标量和序列 - 也许这样的东西对你有用:

def feetToMeters(val):
    try:
        return type(val)(val * 0.3048)
    except TypeError:
        return type(val)(v*0.3048 for v in val)