Você pode explicar fechamentos (como eles se relacionam com Python)?

votos
67

Estive lendo muito sobre fechamentos e acho que entendê-los, mas sem turvação da imagem para mim e para os outros, eu estou esperando que alguém pode explicar fechamentos da forma mais sucinta e claramente quanto possível. Estou à procura de uma explicação simples que pode me ajudar a entender onde e por que eu iria querer usá-los.

Publicado 17/08/2008 em 20:14
fonte usuário
Em outras línguas...                            


13 respostas

votos
75

Encerramento em fechamentos

Os objectos são dados com métodos anexados, fechos são funções com dados ligados.

def make_counter():
    i = 0
    def counter(): # counter() is a closure
        nonlocal i
        i += 1
        return i
    return counter

c1 = make_counter()
c2 = make_counter()

print (c1(), c1(), c2(), c2())
# -> 1 2 1 2
Respondeu 26/09/2008 em 20:28
fonte usuário

votos
42

É simples: Uma função que faz referência variáveis ​​de um escopo contendo, potencialmente depois de fluxo de controle deixou que âmbito. Essa última parte é muito útil:

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

Note-se que 12 e 4 "desapareceram" dentro de f e g, respectivamente, este recurso é o que fazer fechamentos apropriados F e G.

Respondeu 17/08/2008 em 20:32
fonte usuário

votos
14

Eu gosto disso, definição sucinta áspera :

Uma função que pode se referir a ambientes que não estão mais ativos.

Eu adicionaria

Um fechamento permite associar variáveis em uma função sem passá-los como parâmetros .

Decoradores que aceitam parâmetros são um uso comum para encerramentos. Closures são um mecanismo comum de implementação para esse tipo de "fábrica de função". I freqüentemente optar por usar fechamentos no padrão de estratégia quando a estratégia é modificado por dados em tempo de execução.

Em uma linguagem que permite a definição de bloco anônimo - por exemplo, Ruby, C # - fechamentos pode ser usado para implementar (o montante a) novas novas estruturas de controle. A falta de blocos anônimos está entre as limitações de fechamentos em Python .

Respondeu 17/08/2008 em 21:25
fonte usuário

votos
13

Para ser honesto, eu entendo fechamentos perfeitamente bem, exceto eu nunca fui claro sobre o que exatamente é a coisa que é o "fechamento" e que é tão "fechamento" sobre isso. Eu recomendo que você desistir de procurar qualquer lógica por trás da escolha de prazo.

Enfim, aqui é a minha explicação:

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

bar = foo()
bar()   # print 5

A ideia-chave aqui é que o objeto de função retornou de foo mantém um gancho para o var local 'x' embora 'x' tem ido fora do escopo e deve ser extinta. Este gancho é para o próprio var, não apenas o valor que var tinha na época, então quando bar é chamado, ele imprime 5, não 3.

Também ser claro fechamento que Python 2.x tem limitado: não há nenhuma maneira eu posso modificar dentro 'bar' 'x' porque escrever 'x = bla' iria declarar um local 'x' no bar, não atribuir a 'x' de foo . Este é um efeito colateral de Python de atribuição = declaração. Para contornar esta situação, Python 3.0 introduz a palavra-chave não-local:

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
Respondeu 23/08/2008 em 08:43
fonte usuário

votos
6

Eu nunca ouvi falar de transações que estão sendo usados ​​no mesmo contexto como explicar o que um fechamento é e não há realmente nenhuma semântica de transação aqui.

É chamado de um fecho porque "se fecha sobre" a variável fora (constante) - ou seja, não é apenas uma função, mas um gabinete do ambiente em que a função foi criada.

No exemplo seguinte, chamando o fecho g depois de mudar x também irá alterar o valor de x dentro de g, uma vez que se fecha sobre g x:

x = 0

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


closure = f()
print(closure()) # 0
x = 2
print(closure()) # 4
Respondeu 17/08/2008 em 21:20
fonte usuário

votos
3

Aqui está um caso de uso típico para fechamentos - retornos de chamada para elementos GUI (esta seria uma alternativa para subclasse a classe botão). Por exemplo, você pode construir uma função que será chamado em resposta ao pressionar um botão, e "fechar" sobre as variáveis ​​relevantes no escopo pai que são necessários para o processamento do clique. Desta forma, você pode conectar-se interfaces de muito complicadas a partir da mesma função de inicialização, a construção de todas as dependências para o fechamento.

Respondeu 23/01/2009 em 17:13
fonte usuário

votos
1

Aqui está um exemplo de encerramentos 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
Respondeu 22/09/2015 em 20:16
fonte usuário

votos
1

Em Python, um fecho é um exemplo de uma função que tem variáveis ​​ligadas a ele imutável.

Na verdade, o modelo de dados explica isso em sua descrição de funções __closure__atributo:

Nenhum ou uma tupla de células que contêm ligações para variáveis livres da função. Somente leitura

Para demonstrar isso:

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

closure_instance = enclosure('foo')

Claramente, nós sabemos que agora temos uma função apontada para a partir do nome da variável closure_instance. Ostensivamente, se podemos chamá-lo com um objeto, bar, deve imprimir a corda, 'foo'e qualquer que seja a representação de string baré.

Na verdade, a string 'foo' está ligado à instância da função, e podemos lê-lo diretamente aqui, acessando o cell_contentsatributo da primeira célula (e única) na tupla do __closure__atributo:

>>> closure_instance.__closure__[0].cell_contents
'foo'

Como um aparte, objetos celulares são descritas na documentação da API C:

objetos "célula" são usadas para implementar variáveis ​​referenciados por vários escopos

E podemos demonstrar a utilização do nosso fechamento, notando que 'foo'está preso na função e não muda:

>>> closure_instance('bar')
foo bar
>>> closure_instance('baz')
foo baz
>>> closure_instance('quux')
foo quux

E nada pode mudar isso:

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

Funções parciais

O exemplo dado usa o fechamento, como uma função parcial, mas, se este é o nosso único objectivo, o mesmo objectivo pode ser conseguido com functools.partial

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

Há fechamentos mais complicadas assim que não caberiam o exemplo função parcial, e vou demonstrá-las ainda mais conforme o tempo permite.

Respondeu 18/07/2014 em 04:33
fonte usuário

votos
0

Eu gostaria de compartilhar meu exemplo e uma explicação sobre encerramentos. Fiz um exemplo pitão, e duas figuras para demonstrar estados pilha.

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!')

A saída deste código seria da seguinte forma:

*****      hello      #####

      good bye!    ♥♥♥

Aqui estão duas figuras para mostrar pilhas e o fechamento anexado ao objeto função.

quando a função é retornado de fabricante

quando a função é chamada mais tarde

Quando a função é chamada através de um parâmetro ou uma variável não local, o código tem ligações locais de variáveis ​​tais como margin_top, preenchimento, assim como a, b, n. A fim de garantir o código de função para o trabalho, o quadro de pilha da função fabricante que foi ido atrás longe longa deve ser acessível, que é apoiada no fechamento podemos encontrar juntamente com objeto função 'da mensagem.

Respondeu 12/05/2018 em 04:17
fonte usuário

votos
0

todos nós temos usado Decoradores em python. Eles são bons exemplos para mostrar o que são funções de fechamento em python.

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)

aqui valor final é de 12

Aqui, a função de invólucro é capaz de acessar o objeto func porque invólucro é "fechamento lexical", ele pode acessar seus atributos principais. É por isso, é capaz de acessar o objeto func.

Respondeu 17/04/2018 em 19:00
fonte usuário

votos
0
# 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

Critérios para cumpridas por Closures são:

  1. Devemos ter função aninhada.
  2. função aninhada deve referir-se o valor definido em função da envolvente.
  3. função encerrando deve retornar a função aninhada.

# 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
Respondeu 26/12/2017 em 16:41
fonte usuário

votos
0

Para mim, "fechamentos" são funções que são capazes de lembrar o ambiente em que foram criados. Esta funcionalidade, permite que você use variáveis ​​ou métodos dentro do wich fechamento, de outra forma, você não seria capaz de usar ou porque eles já não existem ou estão fora de alcance devido ao escopo. Vamos olhar para este código em 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"  

ele funciona mesmo quando ambos método, "multiplicar" e "x" variável, não existem mais. Tudo porque a capacidade fechamento de lembrar.

Respondeu 20/09/2013 em 14:39
fonte usuário

votos
-2

A melhor explicação que eu já vi de um fecho foi para explicar o mecanismo. Aconteceu mais ou menos assim:

Imagine a sua pilha do programa como uma árvore degenerada onde cada nó tem apenas um filho eo nó de folha simples é o contexto do seu processo atualmente em execução.

Agora relaxar a restrição de que cada nó pode ter apenas um filho.

Se você fizer isso, você pode ter uma construção ( 'rendimento') que pode retornar de um procedimento sem descartar o contexto local (ou seja, não colocá-la para fora da pilha quando você voltar). A próxima vez que o procedimento é invocado, a invocação pega a pilha velha estrutura (árvore) e continua a execução de onde parou.

Respondeu 18/09/2008 em 18:10
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more