I have in my program a class with a member function that should treat certain objects slightly differently than others. In order to do this, it needs to know which object was passed to it, because these objects would have peculiar data pointed to by their data members.

But it seems that referencing the name of the invoking object is impractical and ill advised. I have also considered creating a new function for these exceptional objects, but then how would the next function down on the stack know to call it?

I suppose I could create another data member as a sort of identifier and test for that when running my function; but that seems like a fairly hacky solution. What is the simplest way to do this?

  • 2
    I can't be sure but it sounds like you're discrbing double dispatch. Done that way you don't need to know what was passed. You call methods on what was passed. They do the knowing. – candied_orange Jul 14 '16 at 23:13
  • Okay. I'll look that up. – Luca Jul 14 '16 at 23:22
  • What is it that distinguishes one object from another? Do they have different classes? Different attributes? – Bryan Oakley Jul 15 '16 at 0:01
  • They both have a matrix data member, but some objects will have their data coming from a critically different source that needs to be treated differently. – Luca Jul 15 '16 at 0:03

There's a couple of ways you can do this:

You can use isinstance to determine what the object's class is:

if isinstance(foo, bar):
elif isinstance(foo, baz):

However, this gets unwieldy quickly with a large number of possible classes, and isn't good OOP.

The OOP way would be to use polymorphism - define a base class with a method that returns the data you need, and then create subclasses:

class Polygon:
  def area(self):
    raise NotImplementedError

class Rectangle(Polygon):
  def area(self):
    return self.width * self.height

class Circle(Polygon):
  def area(self):
    return math.pi * self.radius**2

Then, in your other method:

area = obj.area() # you don't have to worry about what type the object is anymore!

A third, arguably more Pythonic way of going about this is to ask for forgiveness, not permission:

  foo = obj.bar
except AttributeError: # if obj doesn't have a bar attribute, then it must have a baz attribute
  foo = obj.baz

However, if you're using OOP, you should stick with the OOP way of doing things - let polymorphism do all the work.

  • Yes, it seems that using polymorphism was the best option. I was able to implement that in a clean, organized way. – Luca Jul 15 '16 at 16:09
  • @LucaDelSignore Glad to hear it! – user200929 Jul 15 '16 at 18:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.