Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
你能解释一下闭包(因为它们与Python有关)吗?_Python_Functional Programming_Closures - Fatal编程技术网

你能解释一下闭包(因为它们与Python有关)吗?

你能解释一下闭包(因为它们与Python有关)吗?,python,functional-programming,closures,Python,Functional Programming,Closures,我已经读了很多关于闭包的书,我想我理解它们,但是在不影响我自己和其他人的情况下,我希望有人能尽可能简明扼要地解释闭包。我正在寻找一个简单的解释,可以帮助我理解在哪里以及为什么要使用它们。很简单:一个函数引用包含范围中的变量,可能是在控制流离开该范围之后。最后一点非常有用: >>> def makeConstantAdder(x): ... constant = x ... def adder(y): ... return y + constant

我已经读了很多关于闭包的书,我想我理解它们,但是在不影响我自己和其他人的情况下,我希望有人能尽可能简明扼要地解释闭包。我正在寻找一个简单的解释,可以帮助我理解在哪里以及为什么要使用它们。

很简单:一个函数引用包含范围中的变量,可能是在控制流离开该范围之后。最后一点非常有用:

>>> def makeConstantAdder(x):
...     constant = x
...     def adder(y):
...         return y + constant
...     return adder
... 
>>> f = makeConstantAdder(12)
>>> f(3)
15
>>> g = makeConstantAdder(4)
>>> g(3)
7

请注意,12和4分别在f和g中“消失”了,这一特性使f和g成为合适的闭包。

我从未听说过在相同的上下文中使用事务来解释闭包是什么,这里真的没有任何事务语义

它之所以被称为闭包,是因为它“关闭”了外部变量(常量)——也就是说,它不仅仅是一个函数,而是创建函数的环境的一个外壳

在以下示例中,更改x后调用闭包g也将更改g中x的值,因为g在x上关闭:

x = 0

def f():
    def g(): 
        return x * 2
    return g


closure = f()
print(closure()) # 0
x = 2
print(closure()) # 4
我喜欢:

可以引用不再处于活动状态的环境的函数

我想补充一点

闭包允许您将变量绑定到函数中,而无需将它们作为参数传递

接受参数的装饰器通常用于闭包。闭包是这种“函数工厂”的常见实现机制。当策略在运行时被数据修改时,我经常选择在中使用闭包


在一种允许匿名块定义的语言中——例如Ruby、C#——闭包可以用来实现(相当于)新的控制结构。缺少匿名块就是其中之一。

老实说,我完全理解闭包,只是我从来都不清楚到底什么是“闭包”,什么是“闭包”。我建议你放弃寻找术语选择背后的逻辑

无论如何,我的解释是:

def foo():
   x = 3
   def bar():
      print x
   x = 5
   return bar

bar = foo()
bar()   # print 5
这里的一个关键思想是,从foo返回的函数对象保留了一个到本地变量“x”的钩子,即使“x”已超出范围并且应该失效。这个钩子指向var本身,而不仅仅是var当时的值,所以当调用bar时,它会打印5,而不是3

还要清楚的是,Python2.x的闭包有限:我无法在“bar”中修改“x”,因为写入“x=bla”将在bar中声明一个本地“x”,而不是分配给foo的“x”。这是Python赋值=声明的副作用。为了解决这个问题,Python 3.0引入了非本地关键字:

def foo():
   x = 3
   def bar():
      print x
   def ack():
      nonlocal x
      x = 7
   x = 5
   return (bar, ack)

bar, ack = foo()
ack()   # modify x of the call to foo
bar()   # print 7

我所见过的关于闭包的最好解释就是解释其机制。事情是这样的:

将程序堆栈想象成一棵退化树,其中每个节点只有一个子节点,而单个叶节点是当前执行过程的上下文

现在,放松每个节点只能有一个子节点的约束

如果这样做,就可以得到一个构造(“yield”),它可以从过程中返回,而不会丢弃本地上下文(即,返回时不会将其从堆栈中弹出)。下一次调用该过程时,调用将拾取旧堆栈(树)帧并继续执行它停止的位置。

对象是带有方法的数据 附加,闭包是具有 所附资料


这里是一个典型的闭包用例——GUI元素的回调(这是对button类进行子类化的一种替代方法)。例如,您可以构造一个函数,该函数将在按下按钮时被调用,并在父作用域中处理单击所需的相关变量上“关闭”。通过这种方式,您可以从相同的初始化函数连接非常复杂的接口,将所有依赖项构建到闭包中。

对我来说,“闭包”是能够记住它们创建的环境的函数。此功能允许您在闭包中使用变量或方法,换句话说,您将无法使用这些变量或方法,因为它们不再存在,或者由于作用域的原因无法使用。让我们看看ruby中的这段代码:

def makefunction (x)
  def multiply (a,b)
    puts a*b
  end
  return lambda {|n| multiply(n,x)} # => returning a closure
end

func = makefunction(2) # => we capture the closure
func.call(6)    # => Result equal "12"  

即使“乘法”方法和“x”变量不再存在,它也能工作。所有这些都是因为闭包具有记住的功能。

在Python中,闭包是一个函数的实例,该函数的变量是不可变的

事实上,在其对函数“
闭包”属性的描述中:

无或包含函数自由变量绑定的单元元组。只读

为了证明这一点:

def enclosure(foo):
    def closure(bar):
        print(foo, bar)
    return closure

closure_instance = enclosure('foo')
显然,我们知道现在有一个变量名
closure\u instance
指向的函数。表面上,如果我们用一个对象调用它,
bar
,它应该打印字符串,
'foo'
,以及
bar
的任何字符串表示形式

事实上,字符串“foo”绑定到函数的实例,我们可以通过访问
\uuu closure\uu
属性元组中第一个(也是唯一一个)单元的
单元内容
属性,在这里直接读取它:

>>> closure_instance.__closure__[0].cell_contents
'foo'
另外,C API文档中描述了单元格对象:

我们可以演示闭包的用法,注意
'foo'
被卡在函数中,并且没有改变:

>>> closure_instance('bar')
foo bar
>>> closure_instance('baz')
foo baz
>>> closure_instance('quux')
foo quux
没有什么能改变它:

>>> closure_instance.__closure__ = None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: readonly attribute

还有更复杂的闭包不适合部分函数示例,如果时间允许,我将进一步演示它们。

这里是Python3闭包的一个示例

def closure(x):
    def counter():
        nonlocal x
        x += 1
        return x
    return counter;

counter1 = closure(100);
counter2 = closure(200);

print("i from closure 1 " + str(counter1()))
print("i from closure 1 " + str(counter1()))
print("i from closure 2 " + str(counter2()))
print("i from closure 1 " + str(counter1()))
print("i from closure 1 " + str(counter1()))
print("i from closure 1 " + str(counter1()))
print("i from closure 2 " + str(counter2()))

# result

i from closure 1 101
i from closure 1 102
i from closure 2 201
i from closure 1 103
i from closure 1 104
i from closure 1 105
i from closure 2 202
闭包要满足的标准是:

  • 我们必须有嵌套函数
  • 嵌套函数必须引用在封闭函数中定义的值
  • 封闭函数必须返回嵌套函数

  • 我们都有
    >>> from __future__ import print_function # use this if you're in Python 2.
    >>> partial_function = functools.partial(print, 'foo')
    >>> partial_function('bar')
    foo bar
    >>> partial_function('baz')
    foo baz
    >>> partial_function('quux')
    foo quux
    
    def closure(x):
        def counter():
            nonlocal x
            x += 1
            return x
        return counter;
    
    counter1 = closure(100);
    counter2 = closure(200);
    
    print("i from closure 1 " + str(counter1()))
    print("i from closure 1 " + str(counter1()))
    print("i from closure 2 " + str(counter2()))
    print("i from closure 1 " + str(counter1()))
    print("i from closure 1 " + str(counter1()))
    print("i from closure 1 " + str(counter1()))
    print("i from closure 2 " + str(counter2()))
    
    # result
    
    i from closure 1 101
    i from closure 1 102
    i from closure 2 201
    i from closure 1 103
    i from closure 1 104
    i from closure 1 105
    i from closure 2 202
    
    # A Closure is a function object that remembers values in enclosing scopes even if they are not present in memory.
    
    # Defining a closure
    
    # This is an outer function.
    def outer_function(message):
        # This is an inner nested function.
        def inner_function():
            print(message)
        return inner_function
    
    # Now lets call the outer function and return value bound to name 'temp'
    temp = outer_function("Hello")
    # On calling temp, 'message' will be still be remembered although we had finished executing outer_function()
    temp()
    # Technique by which some data('message') that remembers values in enclosing scopes 
    # even if they are not present in memory is called closures
    
    # Output: Hello
    
    # Example 2
    def make_multiplier_of(n): # Outer function
        def multiplier(x): # Inner nested function
            return x * n
        return multiplier
    # Multiplier of 3
    times3 = make_multiplier_of(3)
    # Multiplier of 5
    times5 = make_multiplier_of(5)
    print(times5(3)) # 15
    print(times3(2)) #  6
    
    class Test():
        def decorator(func):
            def wrapper(*args):
                b = args[1] + 5
                return func(b)
            return wrapper
    
    @decorator
    def foo(val):
        print val + 2
    
    obj = Test()
    obj.foo(5)
    
    def maker(a, b, n):
        margin_top = 2
        padding = 4
        def message(msg):
            print('\n’ * margin_top, a * n, 
                ' ‘ * padding, msg, ' ‘ * padding, b * n)
        return message
    
    f = maker('*', '#', 5)
    g = maker('', '♥’, 3)
    …
    f('hello')
    g(‘good bye!')
    
    *****      hello      #####
    
          good bye!    ♥♥♥