获取函数的局部变量

时间:2010-10-17 12:31:05

标签: python unix decorator locals

我正在尝试从装饰器中获取局部变量。一个例子:

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'变量(validate()使用)。搜索了一个多小时后,我感觉很迷茫。这可能吗?

修改: 让我更彻底地描述我的问题:我可以在没有执行some_function的情况下获得字符串“some_prvilege”吗?类似的东西:

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

?谢谢你帮助我到目前为止!

4 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

答案 2 :(得分: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)

答案 3 :(得分: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'