Python 高手编程系列八:缓存

缓存装饰器与参数检查十分相似,不过它重点是关注那些内部状态不会影响输出的函数。

每组参数都可以链接到唯一的结果。这种编程风格是函数式编程(functional programming,参

https://en.wikipedia.org/wiki/Functional_programming)的特点,当输入值有限时可以使用。

因此,缓存装饰器可以将输出与计算它所需要的参数放在一起,并在后续的调用中直

接返回它。这种行为被称为 memoizing(参见 https://en.wikipedia.org/wiki/Memoization),

很容易被实现为一个装饰器:

import time

import hashlib

import pickle

cache = {}

def is_obsolete(entry, duration):

return time.time() - entry'time' > duration

def compute_key(function, args, kw):

key = pickle.dumps((function.name , args, kw))

return hashlib.sha1(key).hexdigest()

def memoize(duration=10):

def _memoize(function):

def __memoize(*args, **kw):

key = compute_key(function, args, kw)

是否已经拥有它了?

if (key in cache and

not is_obsolete(cachekey, duration)):

print('we got a winner')

return cachekey'value'

计算

result = function(*args, **kw)

保存结果

cachekey = {

'value': result,

'time': time.time()

}

return result

return __memoize

return _memoize

利用已排序的参数值来构建 SHA 哈希键,并将结果保存在一个全局字典中。利用 pickle

来建立 hash,这是冻结所有作为参数传入的对象状态的快捷方式,以确保所有参数都满足

要求。举个例子,如果用一个线程或套接字作为参数,那么会引发 PicklingError(参

https://docs.python.org/3/library/pickle.html)。duration 参数的作用是,如果上一次函数

调用已经过去了太长时间,那么它会使缓存值无效。

下面是一个使用示例:

@memoize()

... def very_ very very complex stuff(a, b):
... # 如果在执行这个计算时计算机过热
... # 请考虑中止程序
... return a + b
...
very
very very complex stuff(2, 2)
4
very
very very complex stuff(2, 2)
we got a winner
4
@memoize(1) # 1 秒后令缓存失效
... def very
very very complex stuff(a, b):
... return a + b
...
very
very very complex stuff(2, 2)
4
very
very very complex stuff(2, 2)
we got a winner
4
cache
{'c2727f43c6e39b3694649ee0883234cf': {'value': 4, 'time':
1199734132.7102251)}
time.sleep(2)
very
very very complex _stuff(2, 2)

4

缓存代价高昂的函数可以显著提高程序的总体性能,但必须小心使用。缓存值还可以

与函数本身绑定,以管理其作用域和生命周期,代替集中化的字典。但在任何情况下,更

高效的装饰器会使用基于高级缓存算法的专用缓存库。

代理

代理装饰器使用全局机制来标记和注册函数。举个例子,一个根据当前用户来保护代

码访问的安全层可以使用集中式检查器和相关的可调用对象要求的权限来实现:

class User(object):

def init (self, roles):

self.roles = roles

class Unauthorized(Exception):

pass

def protect(role):

def _protect(function):

def __protect(*args, **kw):

user = globals().get('user')

if user is None or role not in user.roles:

raise Unauthorized("I won't tell you")

return function(*args, **kw)

return __protect

return protect
这一模型常用于 Python Web 框架中,用于定义可发布类的安全性。例如,Django 提供
装饰器来保护函数访问的安全。
下面是一个示例,当前用户被保存在一个全局变量中。在方法被访问时装饰器会检查
他/她的角色:
tarek = User(('admin', 'user'))
bill = User(('user',))
class MySecrets(object):
... @protect('admin')
... def waffle
recipe(self):
... print('use tons of butter!')
...
these
_are = MySecrets()

user = tarek

these_ are.waffle recipe()
use tons of butter!
user = bill
these
are.waffle _recipe()

Traceback (most recent call last):

File "", line 1, in

File "", line 7, in wrap

__main __.Unauthorized: I won't tell you

相关推荐
m沐沐11 分钟前
【深度学习】卷积神经网络 数据增强、保存最优模型实现,详细解读
人工智能·python·深度学习·机器学习·cnn·数据增强
天青色等烟雨..17 分钟前
全流程ArcGISPro空间分析、三维建模、可视化及Python融合应用技术
开发语言·python
极光代码工作室21 分钟前
基于Spark的日志监控与分析平台
大数据·hadoop·python·spark·数据可视化
丰锋ff25 分钟前
1.2 Qt常用基础类型
开发语言·qt
AOwhisky26 分钟前
Python 学习笔记(第十三期)——运维自动化(下·前篇):远程命令执行——paramiko基础篇
运维·python·学习·云原生·自动化·运维开发·paramiko
浊酒南街34 分钟前
subprocess.check_output函数介绍
python
TheBestRucy35 分钟前
RAG知识库问答系统落地:从向量检索到上下文增强的全链路实践
人工智能·python·langchain·aigc·交互
AOwhisky1 小时前
Python 学习笔记(第十四期)——运维自动化(下·中篇):远程文件传输——paramiko进阶篇
运维·python·学习·云原生·自动化·文件传输·paramiko
冰暮流星1 小时前
javascript之String方法介绍
开发语言·javascript·ecmascript
其实防守也摸鱼1 小时前
补天SRC新手入门指南:从0到1的漏洞挖掘之路
网络·python·学习·安全·web安全·数据挖掘·挖洞