装饰已经是类方法的方法? [英] Decorating a method that's already a classmethod?

查看:83
本文介绍了装饰已经是类方法的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天早上我遇到了一个有趣的问题。我有一个看起来像这样的基类:

I had an interesting problem this morning. I had a base class that looked like this:

# base.py
class Base(object):

    @classmethod
    def exists(cls, **kwargs):
        # do some work
        pass

还有一个看起来像这样的装饰器模块:

And a decorator module that looked like this:

# caching.py

# actual caching decorator
def cached(ttl):
    # complicated

def cached_model(ttl=300):
    def closure(model_class):
        # ...
        # eventually:
        exists_decorator = cached(ttl=ttl)
        model_class.exists = exists_decorator(model_class.exists))

        return model_class
    return closure

这是我的子类模型:

@cached_model(ttl=300)
class Model(Base):
    pass

事实是,当我实际调用Model.exists时,我收到有关参数数量错误的投诉!检查装饰器中的参数不会显示任何奇怪的现象-这些参数正是我所期望的,并且与方法签名匹配。如何在已经用 classmethod 装饰的方法中添加更多装饰器?

Thing is, when I actually call Model.exists, I get complaints about the wrong number of arguments! Inspecting the arguments in the decorator shows nothing weird going on - the arguments are exactly what I expect, and they match up with the method signature. How can I add further decorators to a method that's already decorated with classmethod?

不是所有模型都被缓存,但是在每个模型上都存在exist()方法作为类方法,因此不能对装饰器进行重新排序: cached_model 可以将类方法添加到exist(),但是是什么使exist()成为未缓存模型上的类方法?

Not all models are cached, but the exists() method is present on every model as a classmethod, so re-ordering the decorators isn't an option: cached_model can add classmethod to exists(), but then what makes exists() a classmethod on uncached models?

推荐答案

类方法 class 参数。解决方法是编辑我的类装饰闭包:

The classmethod decorator actually prepends a class argument to calls to the method, in certain circumstances, as far as I can tell, in addition to binding the method to the class. The solution was editing my class decoration closure:

def cached_model(ttl=300):
    def closure(model_class):
        # ...
        # eventually:
        exists_decorator = cached(ttl=ttl, cache_key=exists_cache_key)
        model_class.exists = classmethod(exists_decorator(model_class.exists.im_func))

        return model_class
    return closure

im_func 属性似乎是对原始函数的引用,它使我可以使用缓存装饰器进入并装饰原始函数,然后将整个混乱包裹在<$ c $中c> classmethod 调用。总结, classmethod 装饰不能堆叠,因为似乎已注入参数。

The im_func property appears to get a reference to the original function, which allows me to reach in and decorate the original function with my caching decorator, and then wrap that whole mess in a classmethod call. Summary, classmethod decorations are not stackable, because arguments seem to be injected.

这篇关于装饰已经是类方法的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆