2015-08-26 31 views
6

Bu yüzden son zamanlarda işlev kapanışı kavramını anlıyorum. Anladığım kadar olduğu gibiPython, işlev kapatma işlevinin adını nasıl saklar?

def outer(): 
    somevar = [] 
    assert "somevar" in locals() and not "somevar" in globals() 
    def inner(): 
     assert "somevar" in locals() and not "somevar" in globals() 
     somevar.append(5) 
     return somevar 
    return inner 

function = outer() 
somevar_returned = function() 
assert id(somevar_returned) == id(function.func_closure[0].cell_contents) 

, fonksiyon kapatılması amacı bu nesnenin çöp toplama önlemek için, nesneye aktif referansı tutmaktır. Aşağıdaki çalışıyor nedeni budur: şeydir

del outer 
somevar_returned_2 = function() 
assert id(somevar_returned) == id(function.func_closure[0].cell_contents) 
assert id(somevar_returned) == id(somevar_returned_2) 

(her zaman olduğu kadar anladığım gibi) inner fonksiyonun çalıştırılmadan önce, Python halk değişkenler sözlüğünü yeniden. Bu sözlük irade içerir: Verilen cep içeriğine bağlı

  • işlevin kapatma isimlerini varsayılan değeri veya parametreye bağlı
  • işlevin parametreleri isimlerini (ve emsal isimleri üzerine yazabilirsiniz)

Soru, Python'un kapağın adını bağlamasını nerede saklıyor? Onu hiç bir yerde bulamıyorum.

Not: işlevin nitelikler: bizim için Neyse ki

>>> print "\n".join("%-16s : %s" % (e, getattr(function, e)) for e in dir(function) if not e.startswith("_") and e != "func_globals") 
func_closure  : (<cell at 0x2b919f6bc050: list object at [...]>,) 
func_code  : <code object inner at [...], file "<stdin>", line 4> 
func_defaults : None 
func_dict  : {} 
func_doc   : None 
func_name  : inner 
+0

değil emin tam olarak ne anlama geldiğini. .. 'function.func_code.co_varnames'? – mata

cevap

5

Bu piton uygulanmasına bağlıdır. Tahminimce sen CPython'u kastediyorsun.

__code__ (veya func_code) bir piton fonksiyon argümanları ve lokal değişkenler nicelendirilir mantıksal formül sanki "ücretsiz değişkenler" olarak adlandırılır olmayan tüm yerel değişkenlerin adını (ihtiva eden bir co_freevars öznitelik

Bu çeşitli özniteliklerden yerel ve yerel olmayan adlardan hücreye bir eşleme elde edebilirsiniz. co_varnames nitelik listeler

In [35]: function.__code__.co_freevars 
Out[35]: ('somevar',) 

tüm yerel isimler tanımlayın:

In [36]: function.__code__.co_varnames 
Out[36]:() 
In [37]: def outer(): 
    ...:  somevar = [] 
    ...:  def inner(): 
    ...:   x = 1 
    ...:   somevar.append(5) 
    ...:   return somevar 
    ...:  return inner 
    ...: 
    ...: function = outer() 

In [38]: function.__code__.co_varnames 
Out[38]: ('x',) 

co_cellvars yerel isimler fonksiyonları tarafından kullanıldıkları diyor iken:

In [43]: outer.__code__.co_cellvars 
Out[43]: ('somevar',) 
+0

sorusuna cevap vermiyor. Bu gerçekten iyi bir cevap. Yerel sözlükçenin parametrelerden ve kapanış isimlerinden nasıl yeniden oluşturulduğunu sadece doğrulayabilir/açıklayabilir misiniz? – FunkySayu

+0

@FunkySayu Bakıyorum. Yerel ['PyEkort_GetLocals'] (https://hg.python.org/cpython/file/tip/Python/ceval.c#l4433) [' PyFrame_FastToLocalsWithError'] (https: //hg.python.org/CPython/dosya/uç/Nesneler/frameobject.C# l867). Bu konuda anlamadığım şey, python'dan bulunmayan bir "co_localsplus" özniteliğine gönderme yapmasıdır. Her neyse, 'locals' sözlüğünü oluşturmak için' co_varnames', 'co_freevars' vb. – Bakuriu

+0

Belki bu konuda başka bir soru açmak harika olurdu? Cevabınız zaten soruyla uyumlu. – FunkySayu

-1

, Python fonksiyonları birinci sınıf nesnelerdir. Böylece işlev nesnelerini inceleyerek kapanışları biraz daha anlayabiliriz. Ve tüm Python işlevleri, bir kapatma işleviyle ilişkili ek değişkenleri incelememize olanak tanıyan kapatma özniteliğine sahiptir.

>>> def f(): 
...  pass 
... 
>>> repr(f); repr(f.__closure__) 
'<function f at 0x0153A330>' 
'None' 
+0

Tamam, sorun şu ki, işlev kapanışıyla ilişkili (gelecekteki) yerel değişkenin adı nerede? Bu kesinlikle – FunkySayu

İlgili konular