cache.set / get 谁都会用,但 timeout=0 是什么意思?incr 遇到不存在的 key 怎么办?存了 None 怎么区分?改了取出的对象会影响缓存吗?这篇把这些边界一个个试出来。
set('a', 1) → get('a') = 1 get("nope") = None get("nope", "默认") = 默认
add('a', 2)(已存在)返回 False 值仍是 1 ; add("b", 2)(不存在)返回 True
get_or_set('c', lambda: 计算) 第一次: computed 第二次: computed
incr('a') = 2 incr("a", 10) = 12 decr = 11
incr('missing') → ValueError: Key ':1:missing' not found
get_many(['x','y','z']) = {'x': 1, 'y': 2}
delete('x') 返回 True 再 delete 返回 False
has_key('y') = True ; touch('y', 1) = True ; touch 不存在的 = False本文用 LocMem 后端(本进程内存)演示 API;不同后端在 incr 原子性、序列化格式上可能有差异,见第 93 篇。
默认 TIMEOUT = 300 秒(未配置时) timeout=1 秒,1.1 秒后 get = None timeout=0 之后立刻 get = None (等于没缓存) timeout=None get = v (永不过期) timeout=-1 立刻 get = None timeout=2 秒,1 秒后 touch(5),又过 1.5 秒(总共 2.5 秒)get = v (touch 重置了过期时间)
timeout 单位是秒。最常见的误用是把「不过期」写成 timeout=0——实际是「不缓存」。
get('zero') = 0 有这个 key 吗(has_key): True
get('empty') = '' 有这个 key 吗(has_key): True
get('none') = None 有这个 key 吗(has_key): True
get('false') = False 有这个 key 吗(has_key): True
get('absent') = None 有这个 key 吗(has_key): False
用哨兵区分: False (存了 None 时仍然返回 None,不是哨兵) True缓存空结果时常用一个特殊标记值,或者用 has_key(会多一次往返)。
set 之后又修改原对象,缓存里的仍是: {'items': [1, 2]}
取出后修改,再次取: {'items': [1, 2]}
不能 pickle 的对象 → TypeError: cannot pickle NoPickle放进缓存的对象要能 pickle。放模型实例会连带它的 _state 一起序列化,取出后是「一份旧快照」。