【问题标题】:Getting local variables of function获取函数的局部变量
【发布时间】:2010-10-17 12:31:05
【问题描述】:

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

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_prvilege” 执行 some_function 吗?比如:

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

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

【问题讨论】:

  • 几个人提出了基本相同的答案,但不清楚的是您是否需要装饰器包(decorator(validate))。有这个要求吗?
  • 不,这不是必需的。我的问题在这个线程中得到了回答(见下文)。谢谢男孩/女孩!

标签: python unix decorator locals


【解决方案1】:

您的装饰器基本上检查用户是否有权执行给定函数,我实际上不明白为什么要检索(附加)特权到正在包装的函数,但您可以在不添加的情况下执行此操作所有函数的另一个参数。

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】:

您可以将其作为参数传递:

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

【讨论】:

  • 感谢您的回复!不完全是我正在寻找的东西。我想将参数传递给 needs_privilege 而不执行真正的函数(some_function,在这种情况下)。
【解决方案3】:

如果您不需要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)

【讨论】:

  • +1 我试图找到一种方法来表达同样的事情。装饰器包给问题增加了一层额外的复杂性。
  • 谢谢!很遗憾我只能选择一个答案作为解决方案。
【解决方案4】:

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

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'

【讨论】:

  • 感谢您的回答!就像我对unutbu说的那样,可惜我只能选择一个答案!
猜你喜欢
  • 2020-01-11
  • 1970-01-01
  • 1970-01-01
  • 2022-08-02
  • 1970-01-01
  • 1970-01-01
  • 2016-02-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多