【问题标题】:How to determine the class defining a method through introspection如何通过自省确定定义方法的类
【发布时间】:2014-02-23 07:50:44
【问题描述】:

我正在使用redis 商店在flask 中构建一个限速装饰器,它将识别不同端点上的不同限制。 (我意识到那里有许多限制速率的装饰器,但我的用例非常不同,所以我自己滚动是有意义的。)

基本上我遇到的问题是确保我存储在 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 函数在作用域内。给定post 函数,我将如何回到SomeEndpoint 类?这是装饰器的基本布局。这可能会令人困惑,所以这里有一个更具体的装饰器示例。

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 模块,但没有发现任何似乎可以实现此目的的东西。

【问题讨论】:

  • 只是为了确认一下:你需要定义方法的类,而不是对象的类吗?
  • @user2357112 实际上是正确的。
  • 我很确定这是可能的 - Python 3 的 super 做了几乎相同的事情 - 但我不知道该怎么做。
  • @user2357112 感谢您的信任投票。除了insepct,你知道还有什么值得一探的吗?
  • ...废话。 super 使用 compile-time magic,仅当方法在其中使用名称 super 时才会触发。这不是你可以用inspect 复制的东西。

标签: python decorator introspection inspect


【解决方案1】:

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

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'>

【讨论】:

  • 如果有人在一天之内没有找到更好的选择,我会接受这个。它可以工作,但在向装饰器添加参数时变得相对笨拙。
猜你喜欢
  • 1970-01-01
  • 2016-01-14
  • 2014-08-25
  • 2020-06-07
  • 1970-01-01
  • 2013-01-26
  • 2011-12-26
  • 1970-01-01
  • 2013-07-03
相关资源
最近更新 更多