2010-10-17 112 views
3

我想從裝飾器中獲取局部變量。一個例子:獲取函數的局部變量

def needs_privilege(privilege, project=None): 
    """Check whether the logged-in user is authorised based on the 
    given privilege 

    @type privilege: Privilege object, id, or str 
    @param privilege: The requested privilege""" 

    def validate(func, self, *args, **kwargs): 
     """Validator of needs_privillige""" 
     try: check(self.user, privilege, project) 
     except AccessDenied: 
      return abort(status_code=401) 
     else: 
      return func(self, *args, **kwargs) 

    return decorator(validate) 

裝飾功能,這樣後:

@needs_privilege("some_privilege") 
def some_function(): 
    pass 

我想檢索some_function的 'privilige' 變量(其驗證()使用)。經過一個多小時的搜索後,我感覺很迷茫。這可能嗎?

編輯: 讓我多一點徹底形容我的問題:我能得到字符串「some_prvilege」 沒有執行some_function?例如:

a = getattr(module, 'somefunction') 
print a.decorator_arguments 

?感謝您幫助我!

+1

幾個人都拿出了基本相同的答案,但有什麼不清楚的是你是否不需要裝飾包(用'decorator(validate)')。這是一個要求嗎? – snapshoe 2010-10-17 16:33:13

+0

不,這不是要求。我的問題在這個線程中得到了回答(見下文)。謝謝你們/女孩! – Martijn 2010-10-17 17:10:47

回答

3

你的裝飾基本上檢查用戶是否有執行給定功能的權限,我真的不明白爲什麼要檢索(附後)對正在被包裝的函數的特權,但是你可以在不爲你的所有函數添加另一個參數的情況下做到這一點。

def needs_privilege(privilege, project=None): 
    """Check whether the logged-in user is authorised based on the 
    given privilege 

    @type privilege: Privilege object, id, or str 
    @param privilege: The requested privilege""" 

    def validate(func, self, *args, **kwargs): 
     """Validator of needs_privillige""" 
     try: check(self.user, privilege, project) 
     except AccessDenied: 
      return abort(status_code=401) 
     else: 
      return func(self, *args, **kwargs) 
    validate.privelege = privelege 
    return decorator(validate) 

順便說一下你的裝飾應該是這樣的:

def needs_privilege(privilege, project=None): 
    def validate(func): 
     def new_func(self, *args, **kwargs): 
      try: 
       check(self.user, privilege, project) 
      except AccessDenied: 
       return abort(status_code=401) 
      else: 
       return func(self, *args, **kwargs) 
     new_func.privilege = privilege 
     return new_func 
    return validate 
+0

謝謝,但這不是我要找的,對不起。我想在沒有實際執行該功能的情況下檢索「特權」。請參閱我的編輯。 – Martijn 2010-10-17 15:22:07

+0

Mzialla:現在就爲你工作:) – mouad 2010-10-17 15:37:47

+0

是的,非常感謝! – Martijn 2010-10-17 17:11:17

2

你可以把它作爲一個參數:

def needs_privilege(privilege, project=None): 
    """Check whether the logged-in user is authorised based on the 
    given privilege 

    @type privilege: Privilege object, id, or str 
    @param privilege: The requested privilege""" 

    def validate(func, self, *args, **kwargs): 
     """Validator of needs_privillige""" 
     try: check(self.user, privilege, project) 
     except AccessDenied: 
      return abort(status_code=401) 
     else: 
      return func(self, privilege, *args, **kwargs) 

    return decorator(validate) 

@needs_privilege("some_privilege") 
def some_function(privilege): 
    pass 
+0

感謝您的回覆!不是我正在尋找的東西。我希望將參數傳遞給needs_privilege *而不執行真正的函數(在這種情況下爲some_function)。 – Martijn 2010-10-17 15:17:06

0

函數是可以擁有屬性過的對象。您可以在裝飾器中設置屬性。這裏有一個例子:

class TestClass(object): 
    def needs_privilege(privilege, project=None): 
     def wrapper(func): 
      def validate(self, *args, **kwargs): 
       """Validator of needs_privillige""" 
       print 'validator check for %s' % privilege 
       return func(*args, **kwargs) 
      validate.privilege = privilege 
      return validate 

     return wrapper 

    @needs_privilege("foo") 
    def bar(): 
     print "called" 

>>> test.TestClass().bar() 
validator check for foo 
called 
>>> test.TestClass.bar.privilege 
'foo' 
>>> test.TestClass().bar.privilege 
'foo' 
+0

感謝您的回答!就像我對'unutbu'說的,很遺憾我只能選擇一個答案! – Martijn 2010-10-17 17:13:35

1

你的問題就簡單多了,如果你並不需要decorator模塊。 如果不嚴格需要decorator模塊,你可以寫這樣的裝飾:

def needs_privilege(privilege, project=None): 
    def validate(func): 
     def _validate(self, *args, **kwargs): 
      return func(self, *args, **kwargs) 
     _validate.decorator_args=(privilege,project) 
     return _validate 
    return validate 

@needs_privilege("some_privilege") 
def some_function(self): 
    pass 

a = some_function 
print(a.decorator_args) 
# ('some_privilege', None) 
+0

+1我試圖找到一種方式來說這個同樣的事情。裝飾器包爲問題增加了一層額外的複雜性。 – snapshoe 2010-10-17 16:29:25

+0

謝謝!很遺憾,我只能選擇一個答案作爲解決方案。 – Martijn 2010-10-17 17:12:14