简体   繁体   English

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

[英]How to properly incorporate duck-typing to return original type?

I really hope this isn't a duplicate. 我真的希望这不是重复。 I tried to search for my question and I couldn't seem to find it. 我试图搜索我的问题,我似乎无法找到它。

So I have a fairly simple function that converts feet to meters: 所以我有一个相当简单的功能,可以将脚转换为米:

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

This works nicely and accepts ints, floats, arrays, and lists. 这很好用,并接受整数,浮点数,数组和列表。 However, if I put in a list (instead of a numpy array), I'd like to have a list returned. 但是,如果我放入一个列表(而不是一个numpy数组),我想要返回一个列表。 So I wrote this: 所以我写了这个:

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

(Alternatively I could use return list(numpy.array(val) * 0.3084) for the last line if I want to use numpy here, which I don't know if that really matters.) (或者我可以使用return list(numpy.array(val) * 0.3084)作为最后一行,如果我想在这里使用numpy ,我不知道这是否真的很重要。)

Is this the best way to incorporate duck-typing here so that I can avoid the use of the type function? 这是在这里加入duck-typing的最佳方法,这样我就可以避免使用type函数了吗? Originally I tried AttributeError , but it didn't work. 最初我尝试过AttributeError ,但它没有用。 Still, I am weary about TypeError even though it seems to work. 尽管如此,我对TypeError感到厌倦,尽管它似乎有效。

Would it be sacrilegious to use if type(val) is list instead? if type(val) is list而使用if type(val) is list是亵渎神明的?

Would it be sacrilegious to use if type(val) is list instead? if type(val) is list而使用if type(val) is list是亵渎神明的?

Yes, because it doesn't work for subclasses of list. 是的,因为它不适用于列表的子类。 If you want to go this way, at least do isinstance(val, list) . 如果你想这样,至少做isinstance(val, list) Here's a solution that treats lists specially, and convert everything else (including scalars and tuples) to NumPy arrays: 这是一个专门处理列表的解决方案,并将其他所有内容(包括标量和元组)转换为NumPy数组:

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

Note that: 注意:

  • passing an instance of a subclass of list will cause a plain list to be returned; 传递list子类的实例将导致返回一个普通list ;
  • passing a list of lists will cause a list of NumPy arrays to be returned. 传递列表列表将导致返回NumPy数组列表。

You could extend this to handle more types specially, but in general, for each type to be handled, you need to write more code as you need to know how to construct that type. 您可以对此进行扩展以特别处理更多类型,但通常,对于要处理的每种类型,您需要编写更多代码,因为您需要知道如何构造该类型。 Therefore, this kind of type conversion is usually left to client code. 因此,这种类型转换通常留给客户端代码。

Since you already use numpy I would avoid using exceptions here with something like 既然你已经使用了numpy,我会避免在这里使用类似的例外

def feetToMeters(val):
    if numpy.isscalar(val):
        return val * 0.3084
    else:
        return numpy.array(val) * 0.3048

Catching TypeError is dangerous since it could be caused by many things besides a list. 捕获TypeError是危险的,因为它可能是由列表之外的许多东西引起的。 I would generally use isinstance(val, list) for this purpose. 为此,我通常会使用isinstance(val,list)。

The trick is that you are trying to support scalars and sequences - maybe something like this would work for you: 诀窍是你试图支持标量和序列 - 也许这样的东西对你有用:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM