0

In Python, can I write a function that takes objects as inputs and performs different calculations depending on the types of the objects?

For example, say I have two classes: "circle" and "line". I define a circle object A with a radius and centre position, and a circle object B with a different radius and centre position. I then define a line object C with a direction vector and a point along the line.

I would like to write a function that calculates the intersection:

def intersect(obj1,obj2):
    # Returns intersection of two geometric entities

If I input the two circles A and B, I want the function to return the area of intersection of A and B. But if I input circle A and line C, I want the output to be the points (if any) where the line crosses the circle. So intersect(obj1,obj2) will need to somehow read the class of obj1 and obj2, and act accordingly.

Vermillion
  • 1,238
  • 1
  • 14
  • 29
  • 2
    That's not very smart from a consistent interface perspective. `intersect` should e.g. return the point(s) of intersection in either case, then have a separate function to get the overlapping area where such a thing makes geometric sense. This will make your code much easier to reason about. In terms of checking types (see [duck typing](https://docs.python.org/3/glossary.html#term-duck-typing) for why you don't normally do this), use [`isinstance`](https://docs.python.org/3/library/functions.html#isinstance). – jonrsharpe Sep 25 '16 at 12:22
  • That makes more sense, I'll write it to return the two points where the circles cross – Vermillion Sep 25 '16 at 12:30
  • 1
    I think that's wise. Then you can look at e.g. `for point in intersect(...):` and know it makes sense without having to worry about what types the inputs happen to be at that point. – jonrsharpe Sep 25 '16 at 12:31
  • Would it be better to just define a separate function for each kind of intersection? – Vermillion Sep 25 '16 at 12:33
  • That's up to the interface you're designing. Are you (or your users) likely to care, or do you just want to be able to pass any two things to the function and get back a list of any intersecting points? What would the benefit of `circle_intersect`, `line_intersect`, etc. be? You might write those as implementation details, but probably not expose them. – jonrsharpe Sep 25 '16 at 12:37
  • I'm just writing it to learn a bit more about python classes. I'll look into the polymorphism that @paxdiablo mentioned – Vermillion Sep 25 '16 at 12:46
  • 1
    Screwed that up... I think http://stackoverflow.com/questions/9225679/how-to-have-different-input-types-for-the-same-function?noredirect=1&lq=1 covers it – jonrsharpe Sep 25 '16 at 12:56

1 Answers1

5

Yes, you can certainly detect the types of your Python objects and execute different behaviour based on that. The built-in type() method will provide the information you need.

I should stress that this is rather reverting to the procedural paradigm whereas what you may be better off doing in looking into object orientation (specifically polymorphism).

You can also return arbitrary types from a function, so returning the two-dimensional intersection of two circles in one case, and two points of intersection between a circle and line in another, is certainly doable as well.

Again, that's addressing the possibility, not the wisdom. It's certainly possible that I could try to cut down a giant Karri tree with a haddock, but the wisdom of such a move would be, at best, dubious.

By way of example, the following program shows how to return a different type of value, based on the type of the parameter passed in:

def fn(x):
    if type(x) is int:
        return 42
    if type(x) is list:
        return [3.14159,2.71828]
    return None

print(fn(1))
print(fn([1,2]))
print(fn(42.7))

The output is, as expected:

42
[3.14159,2.71828]
None
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953