File size: 2,895 Bytes
937ff6a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
from collections import OrderedDict

class LRUCache:
    """
    Least Recently Used (LRU) Cache.
    設計書で言及されているホットキャッシュのシンプルな実装です。
    """
    
    def __init__(self, max_size: int = 20):
        """
        Args:
            max_size (int): キャッシュの最大サイズ。
        """
        if max_size <= 0:
            raise ValueError("max_size must be a positive integer.")
        self.max_size = max_size
        self._cache = OrderedDict()

    def __contains__(self, key):
        "'key in cache' 構文をサポートします。" 
        return key in self._cache

    def __getitem__(self, key):
        "キーに対応する値を取得し、そのキーを最も最近使用されたものとしてマークします。" 
        if key not in self._cache:
            raise KeyError(f"Key '{key}' not found in cache.")
        
        # アイテムを最後に移動させて「最近使用した」ことを示す
        self._cache.move_to_end(key)
        return self._cache[key]

    def __setitem__(self, key, value):
        "キーと値のペアをキャッシュに追加します。" 
        if key in self._cache:
            # 既存のキーの場合は、最近使用したことを示すために移動
            self._cache.move_to_end(key)
        
        self._cache[key] = value
        
        # キャッシュサイズが上限を超えた場合、最も古く使用されていないアイテムを削除
        if len(self._cache) > self.max_size:
            self._cache.popitem(last=False)

    def get(self, key, default=None):
        "キーが存在しない場合に例外を送出しないバージョンの get です。" 
        if key in self._cache:
            return self[key]
        return default

    @property
    def size(self):
        "現在のキャッシュサイズを返します。" 
        return len(self._cache)

# --- 使用例 ---
if __name__ == "__main__":
    # サイズ3のキャッシュを作成
    cache = LRUCache(max_size=3)
    
    print("--- Cache Operations ---")
    cache['coord_1'] = "Tile 1 Data"
    cache['coord_2'] = "Tile 2 Data"
    cache['coord_3'] = "Tile 3 Data"
    print("Cache after adding 3 items:", cache._cache)
    
    # coord_1にアクセス -> 最近使用されたアイテムになる
    print("\nAccessing 'coord_1'...")
    _ = cache['coord_1']
    print("Cache state:", cache._cache)

    # 新しいアイテムを追加 -> 最も古く使用されていない 'coord_2' が削除される
    print("\nAdding 'coord_4', expecting 'coord_2' to be evicted...")
    cache['coord_4'] = "Tile 4 Data"
    print("Cache state:", cache._cache)

    print("\nIs 'coord_2' in cache?", 'coord_2' in cache)
    print("Is 'coord_3' in cache?", 'coord_3' in cache)
    print("Current cache size:", cache.size)