假设有一个包含类 C
实例的函数 foo
:
def foo(x):
bar = C()
return bar(x)
foo
这个函数会被某个业务反复调用(比如每分钟 10,000 次),有什么办法能够让类 C
的实例化过程(bar = C()
)只在第一次被调用的时候执行一次呢?换句话说,第一次调用生成 bar
对象后,如何把它缓存住,让第二次及后续调用都直接载入这个缓存对象呢?
有几个限制:
1 、C
是在某个第三方库中实现的,因此没法修改源码让 C
成为单例;
2 、函数 foo
的参数格式不允许修改;
3 、foo
可能会被 a.py 调用,也可能被 b.py 调用,我希望在这两个 py 文件执行的过程中 bar
对象是独立存在的,因此好像不适合把 foo
定义为 global
?
如果暂且不考虑限制 3,有没有什么比较好的方法实现?
1
ericls 2021-02-27 23:55:12 +08:00 1
```
class C: def __init__(self): print("here") c_cache = {} def make_c(): import inspect frame = inspect.stack() key = '.'.join([frame[1].filename, frame[1].function]) if key not in c_cache: c_cache[key] = C() return c_cache[key] def foo(): c = make_c() def bar(): c = make_c() for i in range(100): foo() for i in range(100): bar() ``` |
2
ericls 2021-02-27 23:56:45 +08:00 1
|
3
nightwitch 2021-02-28 00:03:41 +08:00 1
https://stackoverflow.com/questions/279561/what-is-the-python-equivalent-of-static-variables-inside-a-function
参考最高赞。Python 里面函数也是 Object,所以可以给函数添加一个属性 |
5
hsfzxjy 2021-02-28 00:10:09 +08:00 via Android
C 的实例化单独拎一个函数,然后套上 lru_cache
|
6
BiteTheDust 2021-02-28 00:10:37 +08:00
把函数封装到一个对象里
|
7
ipwx 2021-02-28 00:15:26 +08:00
|
8
ipwx 2021-02-28 00:17:05 +08:00
顺便如果是对象的话重载 __call__ 就能看上去是函数了。
class Foo(object): ....def __init__(self): ........self.bar = C() ....def __call__(self, x): ........return self.bar(x) a. py: foo = Foo() b. py: foo = Foo() |
11
leafcoder 2021-03-01 10:10:38 +08:00
忽略第 3 条条件可以如下:
class C(object): pass class Demo(object): def __new__(cls, *args, **kwargs): inst = object.__new__(cls, *args, **kwargs) if not hasattr(Demo, 'c_inst'): c_inst = C(*args, **kwargs) Demo.c_inst = c_inst inst.c_inst = Demo.c_inst return inst def __init__(self, *args, **kwargs): pass for i in range(5): o = Demo() print(o, o.c_inst) 输出: >>> (<__main__.Demo object at 0x7f7bd9e95310>, <__main__.C object at 0x7f7bd9e95350>) >>> (<__main__.Demo object at 0x7f7bd9e95390>, <__main__.C object at 0x7f7bd9e95350>) >>> (<__main__.Demo object at 0x7f7bd9e95310>, <__main__.C object at 0x7f7bd9e95350>) >>> (<__main__.Demo object at 0x7f7bd9e95390>, <__main__.C object at 0x7f7bd9e95350>) >>> (<__main__.Demo object at 0x7f7bd9e95310>, <__main__.C object at 0x7f7bd9e95350>) |