如何通过内省确定定义方法的类

时间:2014-01-30 19:50:27

标签: python decorator introspection inspect

我使用flask商店在redis中构建限速装饰器,以识别不同端点上的不同限制。 (我意识到那里有很多限速装饰器,但是我的用例不同以至于我自己滚动它是有意义的。)

基本上我遇到的问题是确保我在redis中存储的密钥是​​特定于类的。我在烧瓶中使用蓝图模式,基本上是这样的:

class SomeEndpoint(MethodView):
    def get(self):
        # Respond to get request
    def post(self):
        # Respond to post request

这里的问题是我希望能够对这些类的post方法进行速率限制,而无需添加任何其他命名约定。在我看来,最好的方法就是这样:

class SomeEndpoint(MethodView):

    @RateLimit  # Access SomeEndpoint class name
    def post(self):
        # Some response

但在装饰器中,只有post函数在范围内。如果给定SomeEndpoint函数,我将如何返回post类?这是装饰器的基本布局。这可能令人困惑,所以这里是装饰者的一个更具体的例子。

class RateLimit(object):
"""
The base decorator for app-specific rate-limiting.
"""
def __call__(self, f):
    def endpoint(*args, **kwargs):
        print class_backtrack(f)  # Should print SomeEnpoint
        return f(*args, **kwargs)
    return endpoint

基本上寻找class_backtrack函数的样子。我已经查看了inspect模块,但我还没有找到任何可以实现此目的的内容。

1 个答案:

答案 0 :(得分:0)

您可以装饰整个类而不仅仅是方法:

def wrap(Class, method):
    def wrapper(self, *args, **kwargs):
        print Class
        return method(self, *args, **kwargs)
    return method.__class__(wrapper, None, Class)

def rate_limit(*methods):
    def decorator(Class):
        for method_name in methods:
            method = getattr(Class, method_name)
            setattr(Class, method_name, wrap(Class, method))
        return Class
    return decorator

@rate_limit('post')
class SomeEndpoint(object):

    def post(self):
        pass

class Subclass(SomeEndpoint):
    pass

a = Subclass()
a.post()
# prints <class 'SomeEndpoint'>