Here is my code:
import os
import pickle
import hashlib
def read_file(path):
# Implement your read_file logic here
pass
def write_file(path, content):
# Implement your write_file logic here
pass
class CachedStaticMethod:
path = "cache"
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
if instance is None:
return self # Return the decorator instance for staticmethod to use
return self.func.__get__(instance, owner) # For regular methods
def __call__(self, *args, **kwargs):
cache_path = self.__get_path(*args, **kwargs)
try:
content = read_file(cache_path)
result = pickle.loads(content)
except Exception as e:
result = self.func(*args, **kwargs)
content = pickle.dumps(result)
write_file(cache_path, content)
return result
def __get_path(self, *args, **kwargs):
class_name = self.func.__qualname__.split('.<locals>', 1)[0]
function_name = self.func.__name__
hash_input = f"{class_name}.{function_name}({args}, {kwargs})".encode("utf-8")
hash_value = hashlib.md5(hash_input).hexdigest()
filename = f"{hash_value}.cache"
return os.path.join(self.path, filename)
class MyClass:
@CachedStaticMethod
@staticmethod
def my_static_method(param1: int, param2: str) -> float:
"""
This is a cached static method of MyClass.
"""
result = 3.14 * param1 + len(param2)
return result
# Usage
result1 = MyClass.my_static_method(5, "hello")
result2 = MyClass.my_static_method(5, "hello") # Should use cached result
print(result1)
print(result2)
This is the Error it’s throwing:
AttributeError Traceback (most recent call
last) in
54
55 # Usage
—> 56 result1 = MyClass.my_static_method(5, "hello")
57 result2 = MyClass.my_static_method(5, "hello") # Should use cached result
58in call(self, *args, **kwargs)
23
24 def call(self, *args, **kwargs):
—> 25 cache_path = self.__get_path(*args, **kwargs)
26
27 try:in __get_path(self, *args, **kwargs)
35
36 def __get_path(self, *args, **kwargs):
—> 37 class_name = self.func.qualname.split(‘.’, 1)[0]
38 function_name = self.func.name
39AttributeError: ‘staticmethod’ object has no attribute ‘qualname‘
>Solution :
This is a Python version issue. staticmethods don’t have a __qualname__ until Python 3.10.
You could access the underlying function with __func__, but you’re already implementing the descriptor protocol yourself, so it’d be easier to just not use staticmethod at all. Handling staticmethod‘s functionality is straightforward and makes using your decorator simpler:
class CachedStaticMethod:
def __init__(self, func):
self.func = func
def __get__(self, instance, owner=None):
if instance is None:
return self
return self.func
...
class MyClass:
# No @staticmethod
@CachedStaticMethod
def my_static_method(...):
...
Also, the way you’ve designed your __get__, you’re only caching calls like MyClass.my_static_method(...). Calls on an instance, MyClass().my_static_method(...), bypass the cache, even though they still don’t receive self. You might want to just remove your __get__ entirely, so all calls use the cache.
If you really want to keep self.func as a staticmethod, then you could do self.func.__func__.__qualname__ to get the qualname.