【问题标题】:python decorators getting function variablepython装饰器获取函数变量
【发布时间】:2014-03-24 21:12:57
【问题描述】:

我有这个代码:

def check_karma(needed_karma, user_karma):
    # check karma or exit
    return True

def hello_world():
    user_karma = 50
    check_karma(20, user_karma)
    print "Hello World"

我可以在这里使用装饰器吗?像这样:

...
@check_karma(20, user_karma)
def hello_world():
    user_karma = 50
    print "Hello World"

我不知道我是否可以访问函数内部的数据,因为我在测试脚本中成功编写了@check_karma(20)。

【问题讨论】:

  • 用参数制作装饰器并不是那么简单...stackoverflow.com/questions/5929107/…
  • 不,装饰器不能访问局部变量。你可以让user_karma 成为hello_world() 的一个参数,否则你想做的事情是不可能的。
  • check_karam 看起来像我经常使用的assert

标签: python python-decorators


【解决方案1】:

是的,在这种情况下可以使用装饰器(实际上它可能是有益的),但是,它不像定义函数那么简单。在这种情况下,您要做的是定义所谓的函子functor 是一个像函数一样工作的类。

例如,假设您有课程Apple。您可以通过执行以下操作来实例化此类的对象:

apple = Apple(color='red')

现在,如果这是一个函子,您可以更进一步,通过使用apple 对象,就好像它是一个函数,通过apple() 调用它。这可用于创建您尝试制作的装饰器。您将在装饰器的定义中初始化 check_karma class,如下所示:

@check_karma(needed_karma)
def hello_world():
    ...

这是因为装饰器必须是返回另一个函数函数。上面的 sn-p 本质上是这样做的:

def hello_world():
    ...
hello_world = check_karma(needed_karma)(hello_world)

然后每次调用 hello_world 时,我们都会调用 check_karmafunctor 返回的函数。 user_karma 可能应该从其他地方请求。

这是一个如何在代码中应用它的示例:

user_karma = 50  # pretend this is where you store `user_karma`.

class KarmaRestrictor:
    def __init__(self, needed_karma):
        self.needed_karma = needed_karma

    def __call__(self, restricted_func):
        # This is the actual decoration routine. This `__call__` descriptor
        # is what makes this class a **functor**.

        def _restricted_func(*args, **kwargs):
            if self.get_user_karma() >= self.needed_karma:
                return restricted_func(*args, **kwargs)
            else:
                # TODO: Maybe have a failure routine?
                pass

        return _restricted_func

    def get_user_karma(self):
        return user_karma  # wherever you store this.

check_karma = KarmaRestrictor  # give this decorator an alias.

@check_karma(20)
def hello_world():
    print 'Hello World'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-07
    • 2012-11-24
    • 1970-01-01
    • 2018-01-21
    • 1970-01-01
    • 2012-02-29
    • 1970-01-01
    • 2013-09-18
    相关资源
    最近更新 更多