2012-07-30 76 views
66

如何將類字段作爲參數傳遞給類方法上的裝飾器?我想要做的是這樣的:具有自我參數的Python類方法裝飾器?

class Client(object): 
    def __init__(self, url): 
     self.url = url 

    @check_authorization("some_attr", self.url) 
    def get(self): 
     do_work() 

它抱怨自我不存在self.url傳遞給裝飾。有沒有解決的辦法?

+0

這是一個你有控制權的自定義裝飾器,還是一個你不能改變的裝飾器? – 2012-07-30 23:35:30

+0

這是我的裝飾器,所以我完全控制它 – Mark 2012-07-30 23:36:19

+0

它在init之前被調用我認爲是問題... – 2012-07-30 23:37:57

回答

98

是的。而不是在類定義時間傳入實例屬性,請在運行時檢查它:

def check_authorization(f): 
    def wrapper(*args): 
     print args[0].url 
     return f(*args) 
    return wrapper 

class Client(object): 
    def __init__(self, url): 
     self.url = url 

    @check_authorization 
    def get(self): 
     print 'get' 

>>> Client('http://www.google.com').get() 
http://www.google.com 
get 

裝飾器攔截方法參數;第一個參數是實例,所以它讀取該屬性。您可以在屬性名作爲一個字符串傳遞給裝飾和使用getattr如果你不想硬編碼的屬性名稱:

def check_authorization(attribute): 
    def _check_authorization(f): 
     def wrapper(self, *args): 
      print getattr(self, attribute) 
      return f(self, *args) 
     return wrapper 
    return _check_authorization 
2

你不行。在課堂上沒有self,因爲沒有實例存在。您需要傳遞它,例如str,其中包含要在實例上查找的屬性名稱,然後返回的函數可以執行此操作,或者完全使用其他方法。

15
from re import search 
from functools import wraps 

def is_match(_lambda, pattern): 
    def wrapper(f): 
     @wraps(f) 
     def wrapped(self, *f_args, **f_kwargs): 
      if callable(_lambda) and search(pattern, (_lambda(self) or '')): 
       f(self, *f_args, **f_kwargs) 
     return wrapped 
    return wrapper 

class MyTest(object): 

    def __init__(self): 
     self.name = 'foo' 
     self.surname = 'bar' 

    @is_match(lambda x: x.name, 'foo') 
    @is_match(lambda x: x.surname, 'foo') 
    def my_rule(self): 
     print 'my_rule : ok' 

    @is_match(lambda x: x.name, 'foo') 
    @is_match(lambda x: x.surname, 'bar') 
    def my_rule2(self): 
     print 'my_rule2 : ok' 



test = MyTest() 
test.my_rule() 
test.my_rule2() 

輸出繼電器: my_rule2:OK

+1

非常感謝你!這應該是被接受的答案。我正在試圖弄清裝飾者的類別方法。 – benshepherd 2017-03-09 12:04:42

+0

@raphael在這個設置中,我似乎無法訪問_lambda或模式。我該如何補救。 – Jonathan 2018-01-18 17:03:32

13

更簡潔的例子可能如下:

#/usr/bin/env python3 
from functools import wraps 

def wrapper(method): 
    @wraps(method) 
    def _impl(self, *method_args, **method_kwargs): 
     return method(self, *method_args, **method_kwargs) + "!" 
    return _impl 

class Foo: 
    @wrapper 
    def bar(self, word): 
     return word 

f = Foo() 
result = f.bar("kitty") 
print(result) 

,它將打印:

kitty!