在装饰器中使用自变量

Posted

技术标签:

【中文标题】在装饰器中使用自变量【英文标题】:Use Self Variable in Decorator 【发布时间】:2022-01-16 04:06:05 【问题描述】:

我正在尝试为我的程序使用缓存,我想让用户选择程序应该缓存多长时间。

class Parent:
    """The Parent Class, Do not import this."""
    def __init__(self, apiKey, cacheTime=300):
        self.key = apiKey
        self.time = cacheTime

class invalidApiKey(Exception):
    """The invalidApiKey error."""

    def __init__(self, *args):
        self.message = args[0]

    def __str__(self):
        return "Invalid API Key (Register at https://url.com/register)- 0 ".format(
            self.message
        )

class Child(Parent):
    @cached(cache=TTLCache(maxsize=1024, ttl=Parent.time))
    async def requestStats(self):

这就是我的代码的样子,我尝试过使用全局变量、环境变量、我自己的装饰器-

class Parent:
    def cache(f):
        def wrapper(*args):
            return cached(cache=TTLCache(maxsize=1024, ttl=args[0].time))
        return wrapper

class Child(Parent):
    @Parent.cache
    async def requestStats(self):

但我收到了ValueError: a coroutine was expected, got <function cached.<locals>.decorator at 0x7f8b5d1e3c10>,我现在不确定如何继续。

TL:DR - 我想使用父类中的 self 变量作为子类中函数的参数。 (如果有影响,我使用this library 进行缓存)

【问题讨论】:

请显示complete 异常回溯,从Traceback (most recent call last): 行开始,格式为代码。 这不是我感兴趣的错误,我只是解释了我在尝试可能的修复时收到的错误,我只是想知道如何在这种情况下使用自变量。你去吧编辑 - 我不知道如何在评论中格式化代码,你去 - mystb.in/PoorAccountHandy.sql 有什么更新吗?这对我来说有点重要,我很想看看如何管理它:) 【参考方案1】:

我可能是错的,但在我看来,你把它复杂化了。您似乎想要一个在实例化而不是定义时参数化的装饰。如果你想使用cached,那么你可以这样做:

from cachetools import TTLCache, cached

class Foo:
    
    def __init__(self, time=600):
        self.bar = cached(TTLCache(maxsize=1024, ttl=time))(self.bar)
 
    def bar(self):
        ...

这里未修饰的方法是在定义时创建的,然后在实例化时用各自的参数 - time 进行修饰。但这有点尴尬,我觉得更好的办法是使用cachedmethod

from cachetools import TTLCache, cachedmethod

class Foo:
    
    def __init__(self, time=600):
        self.cache = TTLCache(maxsize=1024, ttl=time)
 
    @cachedmethod(lambda self: self.cache)
    def bar(self):
        ...

这里的修饰发生在定义处,但使用 cache-function 引用在实例化时设置的缓存对象 - self.cache - 带有单独的参数。

但是:你确定cachetools 可以处理asyncio

【讨论】:

我不确定 cachetools 是否可以处理 asyncio,但它现在似乎工作正常,我会试试你的解决方案,明天再来,ty!

以上是关于在装饰器中使用自变量的主要内容,如果未能解决你的问题,请参考以下文章

装饰器中的 Python Access 函数变量

在使用 pytest 时在装饰器中模拟对象

在装饰器中使用全局嵌套模块

Django:在其他装饰器中重用 login_required 装饰器

在装饰器中修改函数

在装饰器中使用 ProcessPoolExecutor 酸洗 Python 函数失败