[英]Overriding dictionary behaviour Python3
我是使用Python的初學者,正在嘗試在字典中使用搜索功能來搜索鍵為點坐標(2)的numpy數組的鍵。 所以,我想要的是:一個字典,其鍵是numpy數組,其值是整數。 然后,將使用in運算符使用一些公差度量(numpy.allclose函數)來比較鍵。 我知道numpy數組不是可散列的,所以我必須重寫getitem和setitem函數(基於我在如何正確地將dict子類化並重寫__getitem__和__setitem__中找到的內容 )。 但是,如何使這些可哈希化以將它們添加為字典中的鍵? 在這種情況下,如何覆蓋in運算符的行為?
謝謝您的幫助!
Numpy數組不可散列,而元組則可。 因此,如果將數組變成元組,則可以對數組進行哈希處理。 從理論上講,如果您也事先對其進行了四舍五入,則可以利用快速查找的優勢,因為您現在擁有離散點。 但是,由於四舍五入是使用十進制基數完成的,而數字是以二進制存儲的,因此在重新轉換期間會遇到分辨率問題。 可以通過將其轉換為可縮放的整數來規避此問題,但這會使一切變慢。
最后,您只需要編寫一個類即可在數組和元組之間進行實時轉換,就可以了。
一個實現可能看起來像這樣:
import numpy as np
class PointDict(dict):
def __init__(self, precision=5):
super(PointDict, self).__init__()
self._prec = 10**precision
def decode(self, tup):
"""
Turns a tuple that was used as index back into a numpy array.
"""
return np.array(tup, dtype=float)/self._prec
def encode(self, ndarray):
"""
Rounds a numpy array and turns it into a tuple so that it can be used
as index for this dict.
"""
return tuple(int(x) for x in ndarray*self._prec)
def __getitem__(self, item):
return self.decode(super(PointDict, self).__getitem__(self.encode(item)))
def __setitem__(self, item, value):
return super(PointDict, self).__setitem__(self.encode(item), value)
def __contains__(self, item):
return super(PointDict, self).__contains__(self.encode(item))
def update(self, other):
for item, value in other.items():
self[item] = value
def items(self):
for item in self:
yield (item, self[item])
def __iter__(self):
for item in super(PointDict, self).__iter__():
yield self.decode(item)
當查找很多點時,具有矢量化批處理寫入/查找功能的純numpy解決方案可能會更好。 但是,此解決方案易於理解和實施。
代替numpy數組,使用2元組的float作為鍵。 元組是不可哈希的,因為它們是不可變的。
Python字典在后台使用哈希表來快速查找鍵。
編寫closeto
函數並不難。
def closeto(a, b, limit=0.1):
x, y = a
p, q = b
return (x-p)**2 + (y-q)**2 < limit**2
這可用於查找接近的點。 但是隨后您必須遍歷所有鍵,因為鍵查找是准確的。 但是,如果你在修真做到這一點的迭代,它比它快得多for
-loop。
測試(在IPython中,使用Python 3):
In [1]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
: def closeto(a, b, limit=0.1):
: x, y = a
: p, q = b
: return (x-p)**2 + (y-q)**2 < limit**2
:--
In [2]: d = {(0.0, 0.0): 12, (1.02, 2.17): 32, (2.0, 4.2): 23}
In [3]: {k: v for k, v in d.items() if closeto(k, (1.0, 2.0), limit=0.5)}
Out[3]: {(1.02, 2.17): 32}
將數組轉換為可哈希的元組:
In [18]: a1 = np.array([0.5, 0.5])
In [19]: a2 = np.array([1.0, 1.5])
In [20]: d = {}
In [21]: d[tuple(a1)] = 14
In [22]: d[tuple(a2)] = 15
In [23]: d
Out[23]: {(0.5, 0.5): 14, (1.0, 1.5): 15}
In [24]: a3 = np.array([0.5, 0.5])
In [25]: a3 in d
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-25-07c81d61b999> in <module>()
----> 1 a3 in d
TypeError: unhashable type: 'numpy.ndarray'
In [26]: tuple(a3) in d
Out[26]: True
不幸的是,由於您想對比較施加公差,因此您沒有太多選擇,只能遍歷所有鍵以尋找“接近”匹配,無論是將其實現為函數還是內聯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.