利用闭包缓存函数结果

最近想写个监视主机和数据库的程序,其中一个是获取主机的IP地址,一般情况下IP地址是不变的 或者变化频率比较低,而对主机的信息的获取又是比较频繁的,如果每次都要利用socket去获取, 这样就会造成不必要的请求。一开始想的是把IP结果保存到文件中,然后一个去写,一个去读,各自 的频率各自定。但是这样感觉很不优雅(要引入一个文件,然后还要管理两个线程或进程)。

突然脑子里就想到一个词:闭包,以前只是看过概念,但是并没有实践过(没有需求), 感觉这次是个机会,嘿嘿,然后啃啃巴巴地写出来了,最后自己又总结了一下,用装饰器写成了通用的形式。

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
"""利用闭包缓存函数结果"""
import time
from threading import Thread


def cache(timeout: "int 秒" = 3):
    """缓存函数结果"""

    def wrapper(func):
        val = func()

        def update():
            nonlocal val
            while True:
                time.sleep(timeout)
                val = func()

        th = Thread(target=update, daemon=True)
        th.start()

        def get_val():
            return val

        return get_val

    return wrapper


@cache()
def get_time():
    return time.time()


if __name__ == '__main__':
    for i in range(10):
        print(get_time())
        time.sleep(1)

对于闭包,我的理解就是一种访问函数内部变量的途径。闭包函数跟一个类很像,用 nolocal 修饰的变量类似于 类变量, 被装饰的函数类似于 实例。下面是用类来改写的形式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class KK:
    val = None

    def __init__(self):
        self.ini()

    @classmethod
    def ini(cls):
        def update():
            while True:
                cls.val = time.time()
                time.sleep(2)

        th = Thread(target=update, daemon=True)
        th.start()


if __name__ == '__main__':
    h = KK()
    for i in range(10):
        print(h.val)
        time.sleep(1)

孙燕姿的歌百听不厌。