How can I create my own data type in python so that I can overwrite arithmetic operators?

I am currently using Python / Numpy to process geographical / GPS data (loving it!), And I am faced with the repetitive task of calculating the distances between geographical points determined by the coordinate pair pn = [lon, lat] .

I have a function that I use as follows: dist = geodistance(p1, p2) , an analog of Euclidean distance in linear algebra (vector subtraction / difference), but occurs in geodesic (spherical) space instead of a rectangular Euclidean space.

Software, Euclidean distance is given by

 dist = ((p2[0] - p1[0])**2 + (p2[1] - p1[1])**2)**0.5 

Mathematically, this is equivalent to the "idiomatic" (due to lack of a better word) sentence

 dist = p1 - p1 # the "norm" of the vector difference, subtraction. 

I am currently getting my distance as follows:

 p1 = [-51.598354,-29.953363] p2 = [-51.598701,-29.953045] dist = geodistance(p1, p2) print dist >> 44.3904032407 

I would like to do this:

 print p2 - p1 # these points now are from some fancy datatype >> 44.3904032407 

And the ultimate goal:

 track = numpy.array([[-51.203018 -29.996149] [-51.203018 -29.99625 ] [-51.20266 -29.996229] [-51.20229 -29.996309] [-51.201519 -29.99416 ]], dtype=fancy) # (**) or something like print numpy.diff(track) >> ndarray([[ 0. ] [ 7.03531252] [ 39.82663316] [ 41.50958596] [ 172.49825765]]) 

Similarly: if you take two datetime objects and subtract them, the operation returns a timedelta object. I want to subtract two coordinates and get the geodesic distance as a result.

I wonder if the class will work, but dtype (for example, a "subtype" of float32) could help create an array from lists (this is how I read things from xml files).

Thanks a lot!

+4
source share
2 answers

You can define your own types by creating a class and name the method __add__ or __sub__ .

For instance:

 class P(object): def __init__(self, lon, lat): self.lon = lon self.lat = lat def __sub__(self, other): dist = ((other.lon - self.lon)**2 + (other.lat - self.lat)**2)**0.5 return dist 

Given that you are currently getting the coordinates of your points using the list indexing syntax, you can also implement the following:

 class P(object): def __init__(self, lon, lat): self.lon = lon self.lat = lat def __sub__(self, other): dist = ((other[0] - self[0])**2 + (other[1] - self[1])**2)**0.5 return dist def __getitem__(self, key): if key == 0: return self.lon elif key == 1: return self.lat else: raise IndexError def __setitem__(self, key, value): if key == 0: self.lon = value elif key == 1: self.lat = value else: raise IndexError 

(I understand that the above may not be the most elegant way to do this).

Thus, your new class is a replacement for the lists you are currently using.

The Python documentation contains additional information about the double underscore methods that you must write to create your custom types. (The information you are looking for begins about halfway down the page)

+2
source

Python Reference, ยง3.4.8, "Emulating Numeric Types"

In particular, __sub__() .

+3
source

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