2012-10-23 14 views
4

我目前使用Python/Numpy來處理地理/ GPS數據(喜歡它!),並且我正在面臨重複性任務來計算由座標對pn = [lon, lat]定義的地理點之間的距離。如何在python中創建自己的數據類型以便覆蓋算術運算符?

我有一個函數,我這樣使用:dist = geodistance(p1, p2)這是類似於線性代數(向量減法/差異)中的歐幾里得距離,但發生在測地(球形)空間,而不是矩形的歐幾里德空間。

編程,歐氏距離由

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

數學上給出的,這相當於「慣用」(由於缺乏一個更好的詞)句

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

目前,我得到我的距離像這樣:

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

>> 44.3904032407 

我想這樣做:

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

>> 44.3904032407 

和最終目標:

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]]) 

類似的事情是:如果你需要兩個datetime對象和相減,返回一個timedelta對象。我想減去兩個座標並得到測地距離。我想知道一個類是否可以工作,但是dtype(例如float32的「子類型」)在從列表創建數組時會有很大幫助(**這是我從XML文件中讀取數據的方式)。

非常感謝!

+0

調查運算符重載。 –

+0

你可以繼承子類ndarray來重載minus操作符,但在做一些可能會讓人困惑的事情之前,我會考慮三次。也可以添加一個新的方法,比如'.dist()'當然。 numpy文檔有一些簡單的例子。只需添加一個方法,你不需要做太多的工作,否則可能會有點棘手。 – seberg

+0

numpy.array(...,dtype = fancy)會帶來一個問題,那就是你會失去numpy的速度,因爲它會考慮python對象的數組而不是數字。也許你想有一個有時包含一對數字並有時包含一對數組的Coord類型。 –

回答

2

您可以通過創建一個類並編寫__add____sub__方法來定義自己的類型。

例如:

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 

假設您目前得到使用列表索引你的語法點的座標,你也可以實現這些:

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 

(我意識到,以上可能不是最優雅的方式)。

這樣,您的新課程就成爲您當前使用的列表的替代品。

Python documentation包含更多關於您需要編寫以創建用戶定義類型的雙下劃線方法的信息。 (您正在查找的信息大約從頁面中途開始)

+0

正如我目前所瞭解的那樣,我無法直接使用'dtype'關鍵字(如'numpy.array(coordlist,dtype = fancy)'''''''''從列表中創建數組,而是必須創建一個例如Coord類,然後做'numpy.array(CoordList,dtype = object)',不是嗎?如果可能的話,我想有一個實際的數字類型,而不是'object'的子類,但如果這是不可能的,我認爲這將是一條路。目前我很好奇'numeric.Real'抽象基類... – heltonbiker

3

的Python語言參考,§3.4.8,"Emulating numeric types"

具體地說,__sub__()

+0

我已經閱讀過關於它的內容,並且還介紹了抽象基類(例如'number.Real'),但是不能沒有找到一個工作的例子。我應該尋找什麼? – heltonbiker

+0

你不會尋找任何東西。 'a - b'是'a .__ sub__(b)'(除非不是,但那是另一回事)。 –

+0

我的意思是尋找如何創建我的新類型,例如使用'numeric.Real'抽象基類。我可以使用'numpy.array(coordlist,dtype = coordtype)'來創建我的數組嗎?或者我必須將對象繼承下來並像'numpy.array(coordlist,dtype = object)'那樣做,然後將'coordlist'列表Coord(對象)實例? – heltonbiker

相關問題