代码之家  ›  专栏  ›  技术社区  ›  Martijn

获取函数的局部变量

  •  3
  • Martijn  · 技术社区  · 14 年前

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

    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
    

    我想从某个函数中检索“privilige”变量(validate()使用)。搜索了一个多小时后,我觉得很迷茫。这有可能吗?

    编辑 : 让我更详细地描述一下我的问题:我能得到“一些”字符串吗? 没有 执行一些函数?类似:

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

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

    4 回复  |  直到 14 年前
        1
  •  3
  •   mouad    14 年前

    您的修饰器基本上检查用户是否有执行给定函数的权限,我不理解您为什么要检索(附加)要包装的函数的特权,但是您可以这样做,而不必为所有函数添加另一个参数。

    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
    
        2
  •  2
  •   Radomir Dopieralski    14 年前

    可以将其作为参数传递:

    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
    
        3
  •  1
  •   unutbu    14 年前

    如果你不需要 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)
    
        4
  •  0
  •   Robie Basak    14 年前

    函数也是可以有属性的对象。您可以在装饰器中设置属性。下面是一个例子:

    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'