为什么我使用这个装饰功能获得多个输出?

时间:2016-06-14 02:14:17

标签: python python-decorators

我最近从C / C ++迁移到了Python。难以理解闭包和装饰。

声明这些功能(在线博客以此片段代码为例)

def outer(some_func):
    def inner():
        print "Before Foo"
        ret = some_func()
        return ret + 1

    return inner

def foo():
    return 1

当我运行以下代码时

foo = outer(foo)
foo()

我得到了预期的输出

Before Foo
2

但是,如果我不止一次地运行它,我会得到奇怪的输出。我不明白会发生什么。

# Writing it down twice instead of running the same cell 
# twice on my IPython notebook to better explain things here
foo = outer(foo)
foo = outer(foo)    
foo()

输出如下

Before Foo
Before Foo
3

为什么我得到3作为输出,为什么"在Foo"之前打印两次?

编辑: - 当我再次装饰这个功能时会发生什么?现在运行foo = outer(foo)非常清楚。当我再次运行foo = outer(foo)时会发生什么?

3 个答案:

答案 0 :(得分:1)

考虑<table id="datatable-buttons" class="table table-striped table-bordered"> <thead <tr> <th>Date</th> <th>Amt</th> <th>Status</th> </tr> </thead> </table> $(document).ready(function() { //$('#datatable-buttons').DataTable( { var table = $('#datatable-ajax').DataTable( { "ajax": { "url": "scripts/json.php", "dataSrc": "" }, "columns": [ { "data": "date" }, { "data": "amt" }, { "data": "status" }, ] } ); 的每个语句中foo引用的内容。最初你将foo定义为一个总是返回1的函数。虽然你调用了foo=outer(foo),它现在有了一个新值。试着想象一下,在你运行那条线之前用foo相等的方法替换赋值右侧的foo。请记住,你在这里嵌套功能。

有几种方法可以帮助你了解正在发生的事情

  1. 在函数的不同部分添加更多打印语句,以帮助了解被调用的内容以及何时调用。
  2. 除非有理由这样做,否则不要重新分配变量foo。也许选择foo1,foo2等等,这样你就可以回顾之前的foo迭代,更清楚地看到正在发生的构成。

答案 1 :(得分:1)

您再次装饰装饰功能。 outer接受一个函数并返回闭包,当然它本身就是函数。没有什么能阻止您将返回的函数作为参数传递给以下调用,就像您在示例中所做的那样。

如果您更改代码以打印正在调用的函数并返回值,则更容易理解正在进行的操作:

def outer(some_func):
    def inner():
        print "Before inner, func: {0}".format(some_func)
        ret = some_func()
        print "After inner, return: {0}".format(ret + 1)
        return ret + 1

    return inner

def foo():
    return 1

foo = outer(foo)
foo = outer(foo)
foo()

输出:

Before inner, func: <function inner at 0x7f1924b516e0>
Before inner, func: <function foo at 0x7f1924b51668>
After inner, return: 2
After inner, return: 3

答案 2 :(得分:0)

问题hoebenkr,我不明白当你将变量ret分配给函数的参数时,你调用函数。这是将变量声明为函数的事实上的标准吗?它迅速在python中运行?