2014-01-30 55 views
2

我正在使用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功能範圍。考慮到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模塊,但我還沒有找到任何似乎完成此任務的內容。

+0

只是爲了確認:你需要定義的方法,而不是類的對象的類? – user2357112

+0

@ user2357112這實際上是正確的。 –

+0

我很確定這是可能的 - Python 3的「super」幾乎完成了一些工作 - 但我不知道如何去做。 – user2357112

回答

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

如果有人在一天內沒有找到更好的替代方案,我會接受。它可以工作,但是在向裝飾器添加參數時會變得相對笨拙。 –

相關問題