簡體   English   中英

覆蓋字典行為Python3

[英]Overriding dictionary behaviour Python3

我是使用Python的初學者,正在嘗試在字典中使用搜索功能來搜索鍵為點坐標(2)的numpy數組的鍵。 所以,我想要的是:一個字典,其鍵是numpy數組,其值是整數。 然后,將使用in運算符使用一些公差度量(numpy.allclose函數)來比較鍵。 我知道numpy數組不是可散列的,所以我必須重寫getitemsetitem函數(基於我在如何正確地將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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM