装饰已经是类方法的方法? [英] Decorating a method that's already a classmethod?
问题描述
今天早上我遇到了一个有趣的问题。我有一个看起来像这样的基类:
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屋!