{ctypes>只为一个有限的mr}函数创建一个缓存项。代码如下:
from collections import OrderedDict
class MRUDict(OrderedDict):
def __init__(self, capacity = 64):
super().__init__()
self.__checkAndSetCapacity(capacity)
def capacity(self):
return self.__capacity
def setCapacity(self, capacity):
self.__checkAndSetCapacity(capacity)
for i in range(len(self) - capacity):
self.__evict() # will execute only if len > capacity
def __getitem__(self, key):
value = super().__getitem__(key)
# if above raises IndexError, next line won't execute
print("Moving key {} to last i.e. MRU position".format(key))
super().move_to_end(key)
return value
def __setitem__(self, key, value):
if key in self:
super().move_to_end(key)
else: # new key
if len(self) == self.__capacity:
self.__evict()
super().__setitem__(key, value)
def __evict(self):
key, value = self.popitem(last = False) # pop first i.e. oldest item
print("Capacity exceeded. Evicting ({}, {})".format(key, value))
def __checkAndSetCapacity(self, capacity):
if not isinstance(capacity, int):
raise TypeError("Capacity should be an int.")
if capacity == 0:
raise ValueError("Capacity should not be zero.")
self.__capacity = capacity
。。。下面是测试代码:
^{pr2}$现在从输出来看,我在实现__getitem__
函数时有点幼稚,因为__repr__
和{__iter__
,然后__getitem__
)都会导致第一个项目作为MRU移动到最后一个项目,但无法继续,因为迭代器没有“next”项,因为它现在指向最后一个元素。但我不知道我能做些什么来解决这个问题。我应该重新实现__iter__
?在
我不知道如何区分用户的调用__getitem__
和内部调用。当然,解决方法是让用户使用一个find()
方法来完成移动到结束的操作,但是我真的希望能够使用常规语法d[k]
。在
请告知如何解决这个问题。谢谢!在
对于这样复杂的行为变化,研究^{} source code 是值得的。在
实际的
__iter__
方法直接在内部结构(维护项目顺序的双链接列表)上循环。它永远不会直接使用__getitem__
,而只是从链接列表返回键。在你现在遇到的实际问题是,当循环时,你直接访问这些项目:
其中有一个
d[k]
;正是访问将项目5从开始移动到结束。这将更新链接列表,因此当请求下一项时,curr.next
引用现在是根,迭代停止。在解决办法是不要那样做。添加一个专用方法来访问项目而不触发MRU更新。或者您可以重复使用
^{pr2}$dict.get()
,例如:您将使用} 的{}方法,该方法返回一个^{} 实例;请参见^{} source code 。在
.items()
方法,OrderedDict
重用^{你必须改变这种行为:
您必须对
.keys()
和.values()
方法执行相同的操作。在相关问题 更多 >
编程相关推荐