How to implement polymorphic arithmetic operators pythonicly?

I am trying to create a class that will allow me to add / multiply / share objects of the same class together or add / multiply numeric arguments to each member of the class

So, my class is designed for coordinates (I know there are great packages there that do everything I want, better than I could ever hope on my own, but now I'm just curious).

class GpsPoint(object): """A class for representing gps coordinates""" def __init__(self, x, y, z): self.x = x self.y = y self.z = z def __add__(self, other): return GpsPoint(self.x + other.x, self.y + other.y, self.z + other.z) def __radd__(self, other): return GpsPoint(self.x + other, self.y + other, self.z + other) def __str__(self): return "%d, %d, %d" % (self.x, self.y, self.z) 

This was my initial attempt. I found this worked, but only if I first used a numeric argument

 >>foo = GpsPoint(1,2,3) >>print 5 + foo 6, 7, 8 >>print foo + 5 AttributeError: 'int' object has no attribute 'x' 

So what is the pythonic way to do this, is there a pythonic way, is it just plain stupid? I see that the philosophical problem is to use isinstance() , and I know that I could throw try except into the block. I'm just wondering how I should do this.

+4
source share
3 answers

โ€œPythonicโ€ is โ€œasking for forgiveness, not permissionโ€, that is, instead of checking the type, try adding in advance and, if it fails, catch the exception and handle it, for example:

 class GpsPoint(object): """A class for representing gps coordinates""" def __init__(self, x, y, z): self.x = x self.y = y self.z = z def __add__(self, other): try: return GpsPoint(self.x + other.x, self.y + other.y, self.z + other.z) except AttributeError: return GpsPoint(self.x + other, self.y + other, self.z + other) def __radd__(self, other): try: return GpsPoint(self.x + other.x, self.y + other.y, self.z + other.z) except AttributeError: return GpsPoint(self.x + other, self.y + other, self.z + other) def __str__(self): return "%d, %d, %d" % (self.x, self.y, self.z) 
+6
source

You will need to try to determine what other type is, at least to the extent that it is compatible with GpsPoint . If you cannot figure it out, just return NotImplemented , and the interpreter will try to process it from there.

+2
source

Short answer: use isinstance ().

There is no other way to tame the type of "other" in your methods. Also, if you check the sources of many python libraries, you will find that there are many places where isinstance () is used. So this is just a state of the art in python :-).

0
source

Source: https://habr.com/ru/post/1302929/


All Articles