Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If duck-typing in Python, should you test isinstance?

You have a Python class which needs an equals test. Python should use duck-typing but is it (better/more accurate) to include or exclude an isinstance test in the eq function? For example:

class Trout(object):
    def __init__(self, value):
        self.value = value

    def __eq__(self, other):
        return isinstance(other, Trout) and self.value == other.value
like image 854
Noel Evans Avatar asked Mar 23 '12 17:03

Noel Evans


People also ask

Should I use Isinstance in Python?

You can use isinstance in Python to verify that the data you are working with is stored as the appropriate data type. When using Python, check data types as needed. isinstance() is a function built into Python that checks whether a value is stored as a particular data type.

What does duck typing mean in Python?

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.

How does Python Isinstance work?

Python isinstance() Function The isinstance() function returns True if the specified object is of the specified type, otherwise False . If the type parameter is a tuple, this function will return True if the object is one of the types in the tuple.

What is duck typing in Python illustrate with an example?

Duck Typing is a type system used in dynamic languages. For example, Python, Perl, Ruby, PHP, Javascript, etc. where the type or the class of an object is less important than the method it defines. Using Duck Typing, we do not check types at all.


2 Answers

Using isinstance in __eq__ methods is pretty common. The reason for this is that if the __eq__ method fails, it can fallback on an __eq__ method from another object. Most normal methods are called explicitly, but __eq__ is called implicitly, so it requires look-before-you-leap more frequently.

EDIT (thanks for the reminder, Sven Marnach):

To make it fallback, you can return the NotImplemented singleton, as in this example:

class Trout(object):
    def __init__(self, value):
        self.value = value

    def __eq__(self, other):
        if isinstance(other, Trout):
            return self.value == other.value
        else:
            return NotImplemented

Suppose a RainbowTrout knows how to compare itself to a Trout or to another RainbowTrout, but a Trout only knows how to compare itself to a Trout. In this example, if you test mytrout == myrainbowtrout, Python will first call mytrout.__eq__(myrainbowtrout), notice that it fails, and then call myrainbowtrout.__eq__(mytrout), which succeeds.

like image 158
amcnabb Avatar answered Oct 18 '22 09:10

amcnabb


Using isintsance() is usually fine in __eq__() methods. You shouldn't return False immediately if the isinstance() check fails, though -- it is better to return NotImplemented to give other.__eq__() a chance of being executed:

def __eq__(self, other):
    if isinstance(other, Trout):
        return self.x == other.x
    return NotImplemented

This will become particularly important in class hierarchies where more than one class defines __eq__():

class A(object):
    def __init__(self, x):
        self.x = x
    def __eq__(self, other):
        if isinstance(other, A):
            return self.x == other.x
        return NotImplemented
class B(A):
    def __init__(self, x, y):
        A.__init__(self, x)
        self.y = y
    def __eq__(self, other):
        if isinstance(other, B):
            return self.x, self.y == other.x, other.y
        return NotImplemented

If you would return False immediately, as you did in your original code, you would lose symmetry between A(3) == B(3, 4) and B(3, 4) == A(3).

like image 38
Sven Marnach Avatar answered Oct 18 '22 09:10

Sven Marnach