Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. 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.)

Is this the best way to incorporate duck-typing here so that I can avoid the use of the type function? Originally I tried AttributeError, but it didn't work. Still, I am weary about TypeError even though it seems to work.

Would it be sacrilegious to use if type(val) is list instead?

like image 799
carmenism Avatar asked Jul 10 '12 21:07

carmenism


People also ask

What is the principle of duck typing?

Duck Typing is a term commonly related to dynamically typed programming languages and polymorphism. The idea behind this principle is that the code itself does not care about whether an object is a duck, but instead it does only care about whether it quacks.

Why must we use duck typing?

Duck typing is a concept related to dynamic typing, where the type or the class of an object is less important than the methods it defines. When you use duck typing, you do not check types at all. Instead, you check for the presence of a given method or attribute.

What is the difference between duck typing and inheritance?

With duck typing you can introduce subtle bugs in your code due this lack of formal relationship. If your "quack" isn't a "quack" at all, you'll be in trouble. With inheritance, this is less likely to happen due the contractual nature of subclassing abstract classes.

Is duck typing good?

advantage is that it leads to fewer lines of code. This makes it look cleaner; thus making your code easier to read and faster to write. practices, it really is useful functionality!


1 Answers

Would it be sacrilegious to use if type(val) is list instead?

Yes, because it doesn't work for subclasses of list. If you want to go this way, at least do isinstance(val, list). Here's a solution that treats lists specially, and convert everything else (including scalars and tuples) to NumPy arrays:

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;
  • passing a list of lists will cause a list of NumPy arrays to be returned.

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.

like image 90
Fred Foo Avatar answered Oct 22 '22 11:10

Fred Foo