两种类级别的cache实现 2023-04-07

2023-04-06  本文已影响0人  9_SooHyun
import functools
import threading
import methodtools


class Parent:
    """
    class level cache implement
    提供两种类级别的cache实现
    第一种是与子类共享cache存储空间的实现
    第二种是类各自私有的cache存储空间的实现
    """

    # cached classmethod. the storage lifetime follows this `Parent` class
    # this way will share the single storage to all its subclasses
    @classmethod
    @functools.lru_cache(maxsize=1)
    def shared_cache(cls, key: str):
        print(cls.__name__, 'functools.lru_cache', key)
        return threading.Lock()

    # cached classmethod. the storage lifetime follows this `Parent` class
    # this way will bind the cache storages to each classes
    @methodtools.lru_cache(maxsize=1)  # note that methodtools wraps classmethod
    @classmethod
    def private_cache(cls, key: str):
        print(cls.__name__, 'methodtools.lru_cache', key)
        return threading.Lock()

    def instance_method(self):
        print("instance_method")
    
    @classmethod
    def class_method(cls):
        print("class_method")
    
    @staticmethod
    def static_method():
        print("static_method")


class Child(Parent):
    pass

# 番外test: subclass's classmethod is a complete copy of parent's classmethod, not a reference
print(Parent.shared_cache is Child.shared_cache) # False
print(Parent.private_cache is Child.private_cache) # False
print(Parent.class_method is Child.class_method) # false
print(Parent.instance_method is Child.instance_method) # True
print(Parent.static_method is Child.static_method) # True
# 这说明,当类继承发生时,子类中的classmethod是完整地从父类中全拷贝而来,而不是引用同一个method.
# because a class method is 'bound' to the specific class
# 而子类的 static method 和 instance method 都是直接引用父类中的method


ins1 = Parent()
ins2 = Child()

# ----------- test shared_cache -----------
l1 = ins1.shared_cache("1")
l2 = ins2.shared_cache("1")
l3 = Child.shared_cache("1")
# 表面上看ins1和ins2都从shared_cache里面拿"1"对应的值
# 但是被lru_cache装饰过后,最终使用的hashkey会添加上caller的类型等信息,l1和l2对应的key不同
# ins1 和 ins2 是共享cache的,因此 l2 会把 ins1 缓存的l1 踢掉
print(l1 is l2) # False
print(l2 is l3) # True

# ----------- test private_cache -----------
l3 = ins1.private_cache("1")
l4 = Parent().private_cache("1")

l5 = ins2.private_cache("1")
l6 = Child().private_cache("1")

print(l3 is l4) # True
print(l5 is l6) # True
print(l4 is l5) # False
上一篇 下一篇

猜你喜欢

热点阅读