Python: 在另一个函数中定义一个函数

Python: defining a function inside another function

我在另一个函数中定义了一个函数。

def foo():
    x = something
    def bar(list=[]):
        list.append(x)
        return x
    return bar

我有两个问题:

  1. 当我从 foo return bar 时,bar 如何保持对 x 的访问权限?此时,x只在foo内部被知道,但是当我们退出foo时,bar如何知道x是什么?
  2. bar 有一个可变的默认参数。当 returned 函数 bar 超出范围时,这个参数 list 是否从内存中删除?每次我调用它都会越来越大bar,我想确保它在不再使用时被删除。

bar 通过创建 闭包来保持对 x 的访问 :

>>> def foo():
...     x = 42
...     def bar(list=[]):
...         list.append(x)
...         return x
...     return bar
...
>>> func = foo()
>>> func
<function foo.<locals>.bar at 0x7fcae19ac050>
>>> func.__closure__
(<cell at 0x7fcae1b19910: int object at 0x1080d99a0>,)

至于默认参数,你问“当返回的函数 bar 超出范围时,这个参数 list 是否从内存中删除?”。

函数是对象。对象不会超出范围,范围是 变量 的 属性。如果您的函数对象不再被引用,那么就像 any 其他对象一样,它可用于垃圾回收。在 CPython 中,这是在引用计数达到零后 立即 。函数参数的默认值只是存储为一个属性,就像在任何其他对象中一样:

>>> func.__defaults__
([],)
>>>

是的,所有这些都将像往常一样清理干净。如果函数对象是唯一引用它的对象,那么当函数对象不复存在时,列表的引用计数变为零,然后它就可用于垃圾回收。

您可以通过定义一个冗长的终结器并将其用作默认值来向自己展示这一点:

>>> class Bar:
...     def __del__(self):
...         print('goodbye from ', self)
...
>>> def foo():
...     def bar(x=Bar()):
...         x.baz = 42
...     return bar
...
>>> func = foo()
>>> func = foo()
goodbye from  <__main__.Bar object at 0x7fcae1b19950>
>>> func = foo()
goodbye from  <__main__.Bar object at 0x7fcae1b19910>