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 中检索“特权”变量(validate() 使用)。搜索了一个多小时后,我感到很失落。这可能吗?

编辑:让我更彻底地描述一下我的问题:我可以在执行 some_function 的情况下获得字符串“some_prvilege”吗?就像是:

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

? 感谢您到目前为止对我的帮助!

4

4 回答 4

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
于 2010-10-17T13:35:55.840 回答
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
于 2010-10-17T12:35:42.423 回答
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)
于 2010-10-17T16:26:56.607 回答
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'
于 2010-10-17T16:24:45.350 回答