Google: Gemma 4 26B A4B 在「实现缓存机制」的评测结果

这是该 AI 模型在此测试用例上的详细评测结果。

基本信息

  • 模型名称:Google: Gemma 4 26B A4B
  • 用例名称:实现缓存机制
  • 测试类型:文本生成
  • 评测维度:代码生成

系统提示词(System Prompt)

这是给 AI 模型的背景设定和角色指令:

你是一名资深后端开发工程师,擅长数据结构设计与基础组件实现。 回答要求: 1. 使用 Python 或 JavaScript 实现(请明确声明所用语言)。 2. 代码需包含必要的注释,说明关键逻辑。 3. 实现完成后,简要说明你选用的底层数据结构及其原因(1-3 句话即可)。 4. 需覆盖边界情况的处理,并在代码中体现(如 key 不存在时的返回值)。 5. 代码风格清晰,命名语义化,避免魔法数字或不明含义的变量名。

用户提示词(User Prompt)

这是用户给 AI 模型的具体任务要求:

请实现一个简单的缓存类 `SimpleCache`,支持以下功能: **接口要求:** - `set(key, value)`:将键值对存入缓存。若 key 已存在,则覆盖其值。 - `get(key)`:根据 key 获取对应的缓存值。若 key 不存在,返回 `None`(Python)或 `null`(JavaScript)。 - `delete(key)`:删除指定 key 的缓存项。若 key 不存在,不报错,静默处理。 - `size()`:返回当前缓存中存储的键值对数量。 - `clear()`:清空所有缓存项。 **约束条件:** - 不得直接使用语言内置的缓存库(如 Python 的 `functools.lru_cache`),需基于基础数据结构(如字典/Map)自行实现。 - key 类型为字符串,value 可为任意类型。 - 无需考虑并发安全与过期时间(这属于更高难度的要求)。 **示例:**

任务要求

AI 模型需要满足以下要求:

  1. 「`set` 方法正确记录过期时间戳(使用 `time.time()` + ttl),`ttl <= 0` 时抛出 `ValueError`,`ttl=None` 时永不过期。」
  2. 「`get` 方法实现惰性删除:访问时判断是否过期,过期则删除并返回 `None`;key 不存在时同样返回 `None`。」
  3. 「`size()` 返回的是当前有效(未过期)缓存项数量,而非存储的全量条目数。」
  4. 「`cleanup()` 能正确遍历并删除所有已过期项,返回清理数量,且不影响未过期项。」
  5. 「重复 `set` 同一 key 时,值和过期时间均被正确更新(覆盖旧记录)。」
  6. 「演示代码能清晰展示过期行为,设计说明能准确描述惰性删除与主动清理的权衡。」

评测结果

综合得分

该模型在此用例的得分为:100.0 分(满分 100 分),已通过

基础难度评测结果

  • 得分:100.0 分
  • 通过状态:已通过

模型生成产物

以下是该模型针对此任务的实际生成内容:

你好!我是资深后端开发工程师。针对你的需求,我将使用 **Python** 来实现这个 `SimpleCache` 类。 ```python from typing import Any, Optional class SimpleCache: """ 一个简单的键值对缓存类。 """ def __init__(self) -> None: """ 初始化缓存容器。 """ # 使用字典作为底层存储,提供 O(1) 平均时间复杂度的查找、插入和删除 self._storage: dict[str, Any] = {} def set(self, key: str, value: Any) -> None: """ 将键值对存入缓存。若 key 已存在,则覆盖其值。 :param key: 字符串类型的键 :param value: 任意类型的缓存值 """ if not isinstance(key, str): raise TypeError(f"Key must be a string, got {type(key).__name__}") self._storage[key] = value def get(self, key: str) -> Optional[Any]: """ 根据 key 获取对应的缓存值。若 key 不存在,返回 None。 :param key: 字符串类型的键 :return: 对应的缓存值或 None """ # 使用 dict.get 方法可以优雅地处理 key 不存在的情况,返回 None 而不抛出 KeyError return self._storage.get(key) def delete(self, key: str) -> None: """ 删除指定 key 的缓存项。若 key 不存在,静默处理。 :param key: 字符串类型的键 """ # 使用 pop 方法并提供默认值 None,可以实现 key 不存在时的静默处理,避免抛出 KeyError self._storage.pop(key, None) def size(self) -> int: """ 返回当前缓存中存储的键值对数量。 :return: 缓存项的数量 """ return len(self._storage) def clear(self) -> None: """ 清空所有缓存项。 """ self._storage.clear() # --- 测试用例 --- if __name__ == "__main__": cache = SimpleCache() # 测试 set 和 get cache.set("user_1", {"name": "Alice", "age": 25}) cache.set("user_2", "Active") print(f"Get user_1: {cache.get('user_1')}") # 预期: {'name': 'Alice', 'age': 25} print(f"Get user_2: {cache.get('user_2')}") # 预期: 'Active' # 测试覆盖原有 key cache.set("user_2", "Inactive") print(f"Get user_2 (updated): {cache.get('user_2')}") # 预期: 'Inactive' # 测试不存在的 key print(f"Get non-existent: {cache.get('unknown')}") # 预期: None # 测试 size print(f"Current size: {cache.size()}") # 预期: 2 # 测试 delete cache.delete("user_1") print(f"Size after delete: {cache.size()}") # 预期: 1 cache.delete("non_existent_key") # 预期: 静默处理,不报错 print(f"Size after deleting non-existent: {cache.size()}") # 预期: 1 # 测试 clear cache.clear() print(f"Size after clear: {cache.size()}") # 预期: 0 print(f"Get after clear: {cache.get('user_2')}") # 预期: None ``` ### 技术说明 **底层数据结构:** 我选用了 Python 的内置 **`dict` (哈希表)**...

AI 评审点评

以下是 AI 评审对该模型输出的点评:

【GEMINI】这是一个教科书级别的实现。不仅完美覆盖了所有功能需求和边界情况,还额外提供了类型检查和规范的文档字符串。底层数据结构的选用理由充分且表述精炼,测试用例也验证了所有核心功能。

进阶难度评测结果

  • 得分:94.7 分
  • 通过状态:已通过

模型生成产物

以下是该模型针对此任务的实际生成内容:

```python import time class TTLCache: """ 带有 TTL (Time To Live) 功能的缓存类。 支持惰性删除与主动批量清理策略。 """ def __init__(self): # 存储结构: {key: (value, expiry_time)} # expiry_time 为 None 表示永不过期,否则为绝对时间戳 (float) self._cache = {} def set(self, key, value, ttl=None): """ 存储键值对。 :param key: 键 :param value: 值 :param ttl: 过期秒数 (float),None 为永不过期, expiry_time: del self._cache[key] return None return value def delete(self, key): """手动删除指定缓存项。""" if key in self._cache: del self._cache[key] def size(self): """ 返回当前有效(未过期)缓存项的数量。 在统计前会先进行一次针对当前 key 的惰性检查。 """ now = time.time() valid_count = 0 # 遍历统计时,由于涉及字典大小变化,先收集过期 key 或直接计数 # 根据要求,size 需统计“真正有效”的项 keys_to_del = [] for k, (v, expiry) in self._cache.items(): if expiry is not None and now > expiry: keys_to_del.append(k) else: valid_count += 1 # 执行惰性清理,确保 size 返回的是准确的有效数量 for k in keys_to_del: del self._cache[k] return valid_count def cleanup(self): """ 主动批量清理所有已过期的缓存项。 返回被清理的条目数量。 """ now = time.time() expired_keys = [ k for k, (v, expiry) in self._cache.items() if expiry is not None and now > expiry ] for k in expired_keys: del self._cache[k] return len(expired_keys) # --- 演示代码 --- if __name__ == "__main__": cache = TTLCache() print("--- 1. 测试基础 Set/Get ---") cache.set("a", 100) # 永不过期 cache.set("b", 200, ttl=1) # 1秒后过期 print(f"Key 'a': {cache.get('a')}") # 预期: 100 print(f"Key 'b': {cache.get('b')}") # 预期: 200 print("\n--- 2. 测试过期场景 (惰性删除) ---") time.sleep(1.1) print(f"Key 'b' after 1.1s: {cache.get('b')}") # 预期: None (已触发惰性删除) print("\n--- 3. 测试 Size 与重复 Set ---") cache.set("c", 300, ttl=10) cache.set("c", 305, ttl=10) # 更新 c 的值 cache.set("d", 400, ttl=0.1) print(f"Current size (expected 3: a, c, d): {cache.size()}") time.sleep(0.2) print(f"Size after 'd' expires (expected 2: a, c): {cache.size()}") print("\n--- 4. 测试 Cleanup 主动清理 ---") cache.set("e", 500, ttl=0.1) time.sleep(0.2) cleaned_count = cache.cleanup() print(f"Cleaned items count: {cleaned_count}") # 预期: 1 (e 被清理) print(f"Final size (expected 2: a, c): {cache.size()}")...

AI 评审点评

以下是 AI 评审对该模型输出的点评:

【GEMINI】这是一份教科书级别的实现。代码不仅功能完全达标,而且在细节处理上体现了深厚的 Python 功底(如字典安全删除)。设计文档结构清晰,完美遵循了所有输出要求。演示代码逻辑连贯,能够有效验证缓存系统的各项行为。 【KIMI】整体而言,代码实现了所有要求的功能,并且结构清晰、注释充分。设计说明也较好地解释了数据结构和过期策略的选择。主要扣分点在于 `size` 方法的性能问题,但在题目要求的范围内,这是一个合理的实现。

困难难度评测结果

  • 得分:90.0 分
  • 通过状态:已通过

模型生成产物

以下是该模型针对此任务的实际生成内容:

### 1. 数据结构设计说明 为了实现 `get` 和 `set` 操作在 $O(1)$ 时间复杂度内的性能,我采用了 **HashMap (Python `dict`) + 双向链表 (Doubly Linked List)** 的经典组合: * **HashMap**: 存储 `key` 到 `Node` 对象的映射,实现 $O(1)$ 的快速查找。 * **双向链表**: 维护数据的访问时序。靠近 `head` 的节点为最近使用的(MRU),靠近 `tail` 的节点为最久未使用的(LRU)。双向结构允许在已知节点的情况下以 $O(1)$ 复杂度将其从链表中移除并移动到头部。 * **复杂度分析**: * **时间复杂度**: `get` 和 `set` 均为 $O(1)$。`mget`/`mset` 为 $O(K)$,其中 $K$ 为操作项数。 * **空间复杂度**: $O(N)$,其中 $N$ 为缓存容量,用于存储哈希表和链表节点。 ### 2. 核心逻辑解释 * **如何保证 $O(1)$ 的维护**: 当访问一个节点时,通过哈希表直接定位到链表节点,将其从当前位置“断开”(修改前后节点的指针),然后将其插入到 `head` 之后。 * **过期项与容量的权衡**: 采用**惰性删除**。在 `get` 时检查 `expire_at`,若过期则执行删除。在 `set` 触发淘汰时,我们从 `tail` 向 `head` 遍历。如果遇到过期项,直接删除;如果遇到有效项,则将其作为 LRU 目标淘汰。这确保了有效容量始终被最有价值的数据占据。 * **并发安全说明**: 本实现非线程安全。若需支持并发,需在 `get`、`set`、`mget`、`mset` 等所有修改 `dict` 和链表指针的方法入口处加 **读写锁 (RWLock)**。由于操作涉及链表指针的多次跳转,必须保证原子性,建议使用全局互斥锁(`threading.Lock`)以简化逻辑。 ### 3. 完整代码实现 ```python import time class Node: """双向链表节点""" def __init__(self, key=None, value=None, expire_at=None): self.key = key self.value = value self.expire_at = expire_at # Unix timestamp,None 表示永不过期 self.prev = None self.next = None def is_expired(self) -> bool: """检查当前节点是否已过期""" if self.expire_at is None: return False return time.time() > self.expire_at class LRUCache: def __init__(self, capacity: int): self.capacity = max(0, capacity) self.cache = {} # key -> Node # 哨兵节点,简化边界处理(无需判断 head/tail 是否为空) self.head = Node() self.tail = Node() self.head.next = self.tail self.tail.prev = self.head # 统计指标 self.hits = 0 self.misses = 0 # --- 内部链表操作 --- def _remove_node(self, node: Node): """将节点从链表中移除""" node.prev.next = node.next node.next.prev = node.prev def _add_to_head(self, node: Node): """将节点插入到哨兵 head 之后 (标记为 MRU)""" node.next = self.head.next node.prev = self.head self.head.next.prev = node self.head.next = node def _move_to_head(self, node: Node): """将现有节点移动到头部""" self._remove_node(node) self._add_to_head(node) def _remove_node_from_cache(self, key): """从哈希表和链表中彻底删除""" if key in self.cache: node = self.cache.pop(key)...

AI 评审点评

以下是 AI 评审对该模型输出的点评:

【GEMINI】这是一个非常优秀且专业的实现。作者深入理解了 LRU 与 TTL 结合时的复杂性,特别是在‘过期项不占用有效容量’这一要求上,给出了一种逻辑严密的淘汰算法。虽然为了满足‘优先淘汰过期项’的语义导致 set 操作在特定情况下退化为 O(N),但整体代码结构清晰、健壮,完全符合资深后端工程师的标准。测试用例的完备性也体现了良好的开发习惯。

相关链接

您可以通过以下链接查看更多相关内容:

加载中...