(Bunlar Python ile ilgili gibi) kapanışları açıklayabilir misiniz?

oy
67

Ben kapanışları hakkında çok şey okudum ve ben onları anlamak düşünüyorum, ama kendim ve başkaları için resmi karıştırdığın olmadan, birisi kısaca ve açık seçik mümkün olduğunca kapanışları açıklamak umut ediyorum. Nerede ve onları kullanmak istediğiniz neden anlamama yardımcı olabilecek basit bir açıklama arıyorum.

Oluştur 17/08/2008 saat 18:14
kaynak kullanıcı
Diğer dillerde...                            


13 cevaplar

oy
42

Bu basit: ihtiva eden kapsamından değişkenleri başvuran bir fonksiyon-kontrol akışı, bu kapsamı ayrıldı potansiyel sonra. Bu son bit çok yararlıdır:

>>> 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 ve 4 gerektiğini unutmayın f ve g iç sırasıyla bu özellik f ve g doğru kapanışları yapmak budur "kayboldu".

Cevap 17/08/2008 saat 18:32
kaynak kullanıcı

oy
6

Bir kapatma olduğunu açıklayan aynı bağlamda kullanılan işlemlerin duymadım ve gerçekten burada herhangi bir işlem semantik bulunmamaktadır.

o (sabit) dış değişkeni "üzerinde kapatır" çünkü bir kapatma denir - yani, bir fonksiyon ancak işlev oluşturulduğu ortamın bir muhafaza değil işte.

g, x üzerine kapanır yana Aşağıdaki örnekte, x değiştirdikten sonra kapatma g çağrıda da g olan x değerini değiştirecek:

x = 0

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


closure = f()
print(closure()) # 0
x = 2
print(closure()) # 4
Cevap 17/08/2008 saat 19:20
kaynak kullanıcı

oy
14

Sevdiğim bu kaba, özlü tanımı :

Artık aktif olmayan ortamlarda başvurabilir bir işlev.

Ben eklemek istiyorum

Bir kapatma Eğer bir fonksiyonu haline değişkenleri bağlamak için izin verir parametreler olarak ileterek olmadan .

Parametrelerini kabul Dekoratörler kapanışları için ortak bir kullanımdır. Kapaklar "işlevi fabrikasının" bu tür için ortak uygulama mekanizması vardır. Sık sık yer kapanışları kullanmayı tercih Strateji Modeli stratejisi çalışma zamanında verilerle modifiye edildiğinde.

Anonim blok tanımını sağlayan bir dilde - örneğin, Yakut, C # - kapanışları (Ne miktarını kadar) yeni yeni kontrol mekanizmaları uygulamaya koyacağına kullanılabilir. Anonim blokların eksikliği arasındadır Python kapanışları sınırlamaları .

Cevap 17/08/2008 saat 19:25
kaynak kullanıcı

oy
13

Dürüst olmak gerekirse, ben gayet iyi ben tam olarak "kapatma" ve hangi "kapatma" bu konuda bu kadar var olan şey ne olduğu konusunda açık olmamıştı hariç kapanışları anlıyoruz. Sana dönem seçimi geride herhangi mantık arayan vazgeçmek önerilir.

Neyse, işte benim açıklama verilmiştir:

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

bar = foo()
bar()   # print 5

Burada temel fikir, fonksiyon nesne yerel var bir kanca korur foo dönen 'x' olduğunu 'x' kapsam dışında gitti ve feshedilmiş olmalıdır bile. Bu kanca var kendisi etmek, var çubuğu denir, bu nedenle zaman zaman vardı sadece değer, bu 5 değil 3 yazdırır.

X = bla 'yazma 'x' foo atanamıyor, barda yerel 'x' ilan edeceklerini çünkü 'x' içeride 'bar' değiştirebilirsiniz yolu yok: Ayrıca berrak Python 2.x sınırlı olduğunu kapatma olmak . Bu Python'un ataması = beyanının bir yan etkidir. Bundan kaçınmak için, Python 3.0 yerel olmayan anahtar kelimeyi tanıtır:

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
Cevap 23/08/2008 saat 06:43
kaynak kullanıcı

oy
-2

Şimdiye kadar bir kapağın gördüğümüz en iyi açıklama mekanizmasını açıklamak oldu. Bunun gibi bir şey gitti:

Her düğüm sadece bir çocuk ve tek yaprak düğümü olan bir dejenere ağacı olarak program yığını sizin şu anda yürütülen prosedürün bağlamıdır düşünün.

Şimdi her düğüm sadece bir çocuk olabilir kısıtlamayı rahatla.

Bunu ise, yerel bağlamı bırakılmaksızın bir prosedürden, dönebilir bir yapı ( 'verim') sahip olabilir (dönmek zaman yani yığın kapalı pop değildir). prosedür çağrılır dahaki sefere çağırma eski yığın (ağacı) çerçeveyi alır ve kaldığı yerden yürütmeye devam eder.

Cevap 18/09/2008 saat 16:10
kaynak kullanıcı

oy
75

kapanışları üzerinde Kapanış

bağlı yöntemlerle veriler, kilitler bağlı verilerle işlevler nesnelerdir vardır.

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
Cevap 26/09/2008 saat 18:28
kaynak kullanıcı

oy
3

GUI öğeleri için geri aramaları (bu düğmeye sınıfını alt alternatif olacaktır) - Burada kapanışları için tipik bir kullanım durumu var. Örneğin, bir düğmeye basarak yanıt olarak adlandırılan ve tıklama işlemek için gerekli olan ebeveyn kapsamında ilgili değişkenler üzerinde "kapatmak" olacak bir işlev oluşturabilirsiniz. Bu şekilde kapatılması halinde tüm bağımlılıkları bina, aynı başlatma işlevinden oldukça karmaşık arayüzler kadar bağlayabilirsiniz.

Cevap 23/01/2009 saat 15:13
kaynak kullanıcı

oy
0

Benim için "kapanışları" oluşturuldukları çevreyi hatırlamak yetenekli fonksiyonlardır. Bu işlevsellik, size kapatma wich içinde değişkenleri veya yöntemleri kullanmak için izin verir, başka bir şekilde, ya da artık yok çünkü kullanmak mümkün olmaz ya da bağlı kapsamına ulaşamayacağı bulunmaktadır. en yakut bu kodun bakalım:

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"  

hem "çarpma" yöntemi ve "x" değişken, artık var olmayan bile işe yarıyor. Tüm kapatma yeteneği hatırlamak çünkü.

Cevap 20/09/2013 saat 12:39
kaynak kullanıcı

oy
1

Python'da, kapatma immutably kendisine bağlı değişkenler olan bir fonksiyonun bir örneğidir.

Aslında, veri modeli bu açıklar işlevlerin kendi açıklamasında __closure__özniteliği:

Yok veya hücrelerin tanımlama grubu işlevin serbest değişkenler için bağları içerirler. Sadece oku

Bunu göstermek için:

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

closure_instance = enclosure('foo')

Açıkçası, biz şimdi bir işlev değişken adından işaret biliyoruz closure_instance. Biz bir nesneyle dersek Görünüşte, barbu dize, yazdırmalısınız 'foo've ne olursa olsun dize gösterimi barolduğunu.

Aslında, dize 'foo' olan fonksiyonun örneğine bağlı ve doğrudan erişerek, buradan okuyabilirsiniz cell_contentsait başlığın ilk (ve tek) hücrenin niteliğini __closure__özniteliği:

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

bir kenara, hücre nesneleri Cı API belgelerinde açıklanmıştır:

"Hücre" nesneler birden kapsamları tarafından başvurulan değişkenleri uygulamak için kullanılır

Ve biz belirterek, bizim kapatma kullanımını göstermek 'foo'işlevinde sıkıştı ve değişmez:

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

Ve hiçbir şey değiştirebilirsiniz:

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

Kısmi İşlevleri

Verilen örnek kısmi fonksiyon olarak kapatılmasını kullanır, ama bu bizim tek hedefimiz ise, aynı amaç ile gerçekleştirilebilir 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

Orada kısmi fonksiyon örneği uygun olmaz yanı daha karmaşık kapanışları, ve zaman verir gibi ben onları daha da göstermek gerekir.

Cevap 18/07/2014 saat 02:33
kaynak kullanıcı

oy
1

İşte Python3 kapanışları bir örnektir

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
Cevap 22/09/2015 saat 19:16
kaynak kullanıcı

oy
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

Kapalı Yolu tarafından karşılanması için kriterler şunlardır:

  1. Biz iç içe işlevi olmalıdır.
  2. İç içe fonksiyon parça işlevi belirtilen değere başvurmalıdır.
  3. fonksiyonunu Çevreleyen iç içe işlevini geri dönmelidir.

# 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
Cevap 26/12/2017 saat 14:41
kaynak kullanıcı

oy
0

Hepimizin kullandık dekoratörler python. Onlar Python kapatma fonksiyonları göstermek için güzel örneklerdir.

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)

Burada nihai değeri 12'dir

sarıcı "sözcük kapatma" olduğu için burada, sarıcı işlevi fonk nesneye erişebilir, bunun ana özelliklerini bulunuyor erişebilirsiniz. o fonk nesneye erişebilir olmasının nedeni, budur.

Cevap 17/04/2018 saat 18:00
kaynak kullanıcı

oy
0

Benim örnek ve kapanışları hakkında bir açıklama paylaşmak istiyorum. I yığın durumlarını göstermek için bir piton örnek ve iki rakamlar yaptı.

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şağıdaki gibi bu kodun çıktısı şöyle olacaktır:

*****      hello      #####

      good bye!    ♥♥♥

Burada yığın ve işlev nesnesine bağlı kapatma göstermek için iki rakamlardır.

fonksiyon makinesi dönen edildiğinde

fonksiyon sonradan çağrıldığında

fonksiyon, bir parametre veya yerel olmayan bir değişken üzerinden çağrıldığında, kodu lokal değişkeni, margin_top olarak bağlamaları, dolgu olarak, a, b, n gerekmektedir. işe fonksiyon kodunu sağlamak amacıyla, kapatma yedeklenir erişilebilir olmalıdır uzak uzun zaman önce gitmişti yapımcısı fonksiyonunun yığın çerçevesi biz 'iletinin işlevi nesnesi ile birlikte bulabilirsiniz.

Cevap 12/05/2018 saat 03:17
kaynak kullanıcı

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