νμ΄μ¬μμ μ€μ²© ν¨μλ₯Όλ³΄κ³ μ¬μ©νμΌλ©° ν΄λ‘μ μ μμ μΌμΉν©λλ€. μ nested functions
λμ μ κ·Έλ€μ λΆλ €μ§ closures
λκ°?
μ€μ²© ν¨μλ μΈλΆ μΈκ³μμ μ¬μ©λμ§ μκΈ° λλ¬Έμ ν΄λ‘μ κ° μλκ°?
μ λ°μ΄νΈ : ν΄λ‘μ μ λν΄ μ½κ³ μμκ³ νμ΄μ¬κ³Ό κ΄λ ¨ νμ¬μ΄ κ°λ μ λν΄ μκ°νκ²νμ΅λλ€. μλ μ£Όμμμ λκ΅°κ°κ° μΈκΈ ν κΈ°μ¬λ₯Ό κ²μνκ³ μ°Ύμμ§λ§ ν΄λΉ κΈ°μ¬μ μ€λͺ μ μμ ν μ΄ν΄ν μ μμΌλ―λ‘μ΄ μ§λ¬Έμνλ μ΄μ μ λλ€.
λ΅λ³
νμλ ν¨μκ° μ€νμ μλ£ ν λλ¬μΈλ λ²μμμ λ‘컬 λ³μμ μ‘μΈμ€ ν λ λ°μν©λλ€.
def make_printer(msg):
def printer():
print msg
return printer
printer = make_printer('Foo!')
printer()
make_printer
νΈμΆ λλ©΄ printer
ν¨μμ λν μ»΄νμΌ λ μ½λ κ° μμ λ° msg
λ‘컬 κ°μΌλ‘ μ€νμ μ νλ μμ΄ λ°°μΉλ©λλ€ . κ·Έλ° λ€μ ν¨μλ₯Ό μμ±νκ³ λ¦¬ν΄ν©λλ€. ν¨μ printer
λ msg
λ³μλ₯Ό μ°Έμ‘° νλ―λ‘ make_printer
ν¨μκ° λ°ν λ νμλ κ³μ μ μ§λ©λλ€ .
λ°λΌμ μ€μ²© ν¨μκ° κ·Έλ μ§ μμΌλ©΄
- λλ¬μΈλ λ²μμ λ‘컬 μΈ λ³μμ μ‘μΈμ€
- κ·Έκ²λ€μ΄ κ·Έ λ²μ λ°μμ μ€νλ λ κ·Έλ κ²νμμμ€.
κ·Έλ€μ νμλμ§ μμ΅λλ€.
λ€μμ ν΄λ‘μ κ° μλ μ€μ²© ν¨μμ μμ λλ€.
def make_printer(msg):
def printer(msg=msg):
print msg
return printer
printer = make_printer("Foo!")
printer() #Output: Foo!
μ¬κΈ°μλ κ°μ λ§€κ° λ³μμ κΈ°λ³Έκ°μ λ°μΈλ©ν©λλ€. μ΄κ²μ ν¨μ printer
κ° μμ± λ λ λ°μ νλ―λ‘ λ¦¬ν΄ νμ msg
external κ°μ λν μ°Έμ‘°λ₯Ό printer
μ μ§ν νμκ° μμ΅λλ€ make_printer
. μ΄ λ¬Έλ§₯ msg
μμ ν¨μμ μΌλ°μ μΈ μ§μ λ³μ μΌλΏ printer
μ
λλ€.
λ΅λ³
μ΄ μ§λ¬Έμ μ΄λ―Έ aaronasterling λ μ μν΄ λ΅λ³λμμ΅λλ€
κ·Έλ¬λ λκ΅°κ° λ³μκ° νλ μλμ μ μ₯λλ λ°©μμ κ΄μ¬μ΄μμ μ μμ΅λλ€.
μ€ λν«μ μ€κΈ° μ μ :
ν΄λ‘μ λ μ ν΄λ‘μ§ νκ²½μμ λ³μλ₯Ό μμνλ ν¨μμ λλ€. ν¨μ μ½λ°±μ I / Oλ₯Ό μννλ λ€λ₯Έ ν¨μμ λν μΈμλ‘ μ λ¬νλ©΄μ΄ μ½λ°± ν¨μκ° λμ€μ νΈμΆλλ©°μ΄ ν¨μλ κ±°μ λ§μ μ²λΌ μ¬μ© κ°λ₯ν λͺ¨λ λ³μμ ν¨κ» μ μΈ λ 컨ν μ€νΈλ₯Ό κΈ°μ΅ν©λλ€. κ·Έ λ§₯λ½μμ.
-
ν¨μκ° μμ λ³μλ₯Ό μ¬μ©νμ§ μμΌλ©΄ ν΄λ‘μ λ₯Ό νμ±νμ§ μμ΅λλ€.
-
μμ λ³μλ₯Ό μ¬μ©νλ λ€λ₯Έ λ΄λΆ λ 벨μ΄μλ ββκ²½μ° λͺ¨λ μ΄μ λ 벨μ μ΄ν νκ²½μ μ μ₯ν©λλ€ (μ : λμ)
-
κΈ°λ₯ μμ±
func_closure
μ νμ΄μ¬ <3.x λλ__closure__
μμ λ³μ μ μ₯ νμ΄μ¬> 3.X. -
νμ΄μ¬μ λͺ¨λ ν¨μμλμ΄ νμ μμ±μ΄ μμ§λ§ μμ λ³μκ° μμΌλ©΄ λ΄μ©μ μ μ₯νμ§ μμ΅λλ€.
μ : μμ λ³μκ° μμΌλ―λ‘ ν΄λ‘μ μμ±μ΄ μμ§λ§ λ΄μ©μ΄ μμ΅λλ€.
>>> def foo():
... def fii():
... pass
... return fii
...
>>> f = foo()
>>> f.func_closure
>>> 'func_closure' in dir(f)
True
>>>
μ£Όμ : λ¬΄λ£ λ³μ λ νμλ₯Ό λ§λ€μ΄μΌν©λλ€.
μμ λμΌν μ€ λν«μ μ¬μ©νμ¬ μ€λͺ ν©λλ€.
>>> def make_printer(msg):
... def printer():
... print msg
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer() #Output: Foo!
κ·Έλ¦¬κ³ λͺ¨λ νμ΄μ¬ ν¨μμλ ν΄λ‘μ μμ±μ΄ μμΌλ―λ‘ ν΄λ‘μ ν¨μμ κ΄λ ¨λ λλ¬μΈλ λ³μλ₯Ό μ΄ν΄ λ³΄κ² μ΅λλ€.
func_closure
ν¨μ μ μμ±μ λ€μκ³Ό κ°μ΅λλ€printer
>>> 'func_closure' in dir(printer)
True
>>> printer.func_closure
(<cell at 0x108154c90: str object at 0x108151de0>,)
>>>
μ΄ closure
μμ±μ λλ¬μΈλ λ²μμ μ μ λ λ³μμ μΈλΆ μ¬νμ ν¬ν¨νλ μ
μ€λΈμ νΈμ ννμ 리ν΄ν©λλ€.
func_closureμ 첫 λ²μ§Έ μμλ ν¨μμ μμ λ³μμ λν λ°μΈλ©μ ν¬ν¨νλ None λλ μ νν μΌ μ μμΌλ©° μ½κΈ° μ μ©μ λλ€.
>>> dir(printer.func_closure[0])
['__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__getattribute__',
'__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
>>>
μμ μΆλ ₯ cell_contents
μμ λ³Ό μμλ λ΄μ© μ 보μ.
>>> printer.func_closure[0].cell_contents
'Foo!'
>>> type(printer.func_closure[0].cell_contents)
<type 'str'>
>>>
λ°λΌμ ν¨μλ₯Ό νΈμΆνλ©΄μ printer()
μ μ₯λ κ°μ μ‘μΈμ€ν©λλ€ cell_contents
. μ΄κ²μ΄ μΆλ ₯μ βFoo!βλ‘ μ»μ λ°©λ²μ
λλ€.
λ€μ μμ μ€ λν«μ μ¬μ©νμ¬ λͺ κ°μ§ λ³κ²½ μ¬νμ μ€λͺ ν©λλ€.
>>> def make_printer(msg):
... def printer():
... pass
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer.func_closure
>>>
μμ μ€ λν«μμλ νλ¦°ν° ν¨μ λ΄λΆμ msgλ₯Ό μΈμνμ§ μμΌλ―λ‘ μ¬μ© κ°λ₯ν λ³μλ₯Ό λ§λ€μ§ μμ΅λλ€. μμ λ³μκ° μμΌλ―λ‘ ν΄λ‘μ μμ λ΄μ©μ΄ μμ΅λλ€. κ·Έκ²μ΄ λ°λ‘ μ°λ¦¬κ° μμμ λ³Έ κ²μ λλ€.
μ§κΈμ λͺ¨λ κ²μ μ·¨μ λ€λ₯Έ λ€λ₯Έ μ‘°κ°μ μ€λͺ
ν κ² Free Variable
μΌλ‘ Closure
:
>>> def outer(x):
... def intermediate(y):
... free = 'free'
... def inner(z):
... return '%s %s %s %s' % (x, y, free, z)
... return inner
... return intermediate
...
>>> outer('I')('am')('variable')
'I am free variable'
>>>
>>> inter = outer('I')
>>> inter.func_closure
(<cell at 0x10c989130: str object at 0x10c831b98>,)
>>> inter.func_closure[0].cell_contents
'I'
>>> inn = inter('am')
κ·Έλμ μ°λ¦¬λ func_closure
μμ±μ΄ ν΄λ‘μ μ
μ ννμ΄λΌλ κ²μ μ μ μμ΅λλ€. μ°λ¦¬λ μμ±κ³Ό κ·Έ λ΄μ©μ λͺ
μ μ μΌλ‘ μ°Έμ‘° ν μ μμ΅λλ€. μ
μλ βcell_contentsβμμ±μ΄ μμ΅λλ€
>>> inn.func_closure
(<cell at 0x10c9807c0: str object at 0x10c9b0990>,
<cell at 0x10c980f68: str object at 0x10c9eaf30>,
<cell at 0x10c989130: str object at 0x10c831b98>)
>>> for i in inn.func_closure:
... print i.cell_contents
...
free
am
I
>>>
μ¬κΈ°μ νΈμΆ inn
νλ©΄ λͺ¨λ μ μ₯ λ¬΄λ£ λ³μλ₯Ό μ°Έμ‘°νλ―λ‘I am free variable
>>> inn('variable')
'I am free variable'
>>>
λ΅λ³
νμ΄μ¬μ ν΄λ‘μ λ₯Ό μ½νκ² μ§μν©λλ€. λ¬΄μ¨ λ»μΈμ§ νμΈνλ €λ©΄ JavaScriptλ‘ ν΄λ‘μ λ₯Ό μ¬μ©νμ¬ λ€μ μΉ΄μ΄ν° μμ λ₯Ό μ¬μ©νμμμ€.
function initCounter(){
var x = 0;
function counter () {
x += 1;
console.log(x);
};
return counter;
}
count = initCounter();
count(); //Prints 1
count(); //Prints 2
count(); //Prints 3
ν΄λ‘μ λ μ΄μ κ°μ΄ μμ±λ ν¨μμ βλ΄λΆ λ©λͺ¨λ¦¬βκΈ°λ₯μ μ 곡νκΈ° λλ¬Έμ λ§€μ° μ°μν©λλ€. νμ΄μ¬ 2.7λΆν°λ λΆκ°λ₯ν©λλ€. λΉμ μ΄ μλνλ©΄
def initCounter():
x = 0;
def counter ():
x += 1 ##Error, x not defined
print x
return counter
count = initCounter();
count(); ##Error
count();
count();
xκ° μ μλμ§ μμλ€λ μ€λ₯κ° λ°μν©λλ€. κ·Έλ¬λ λ€λ₯Έ μ¬λλ€μ΄ μΈμ ν μ μλ€λ κ²μ μ΄λ»κ² μ μ μμ΅λκΉ? μ΄κ²μ νμ΄μ¬μ΄ ν¨μ λ³μ λ²μλ₯Ό κ΄λ¦¬νλ λ°©λ² λλ¬Έμ λλ€. λ΄λΆ ν¨μλ μΈλΆ ν¨μμ λ³μλ₯Ό μ½μ μ μμ§λ§ μΈ μλ μμ΅λλ€ .
μ λ§ λΆλλ¬μ΄ μΌμ λλ€. κ·Έλ¬λ μ½κΈ° μ μ© ν΄λ‘μ λ₯Ό μ¬μ©νλ©΄ Pythonμμ ꡬ문 μ€νμ μ 곡 νλ ν¨μ λ°μ½λ μ΄ν° ν¨ν΄ μ μ μ΄λ ꡬνν μ μμ΅λλ€ .
μ΅μ μ 보
μ§μ νλ―μ΄ νμ΄μ¬μ λ²μ μ νμ μ²λ¦¬νλ λ°©λ²μ΄ μμΌλ©° λͺ κ°μ§λ₯Ό 곡κ°νκ² μ΅λλ€.
1.global
ν€μλλ₯Ό μ¬μ©νμμμ€ (μΌλ°μ μΌλ‘ κΆμ₯νμ§ μμ).
2. Python 3.xμμ nonlocal
ν€μλλ₯Ό μ¬μ©νμμμ€ (@unutbu λ° @leewzμμ μ μ).
3. κ°λ¨ν μμ κ°λ₯ν ν΄λμ€ μ μObject
class Object(object):
pass
λ³μλ₯Ό μ μ₯ν Object scope
λ΄λΆ initCounter
λ₯Ό μμ± νμμμ€.
def initCounter ():
scope = Object()
scope.x = 0
def counter():
scope.x += 1
print scope.x
return counter
scope
μ€μ λ‘λ μ°Έμ‘° μΌ λΏμ΄ λ―λ‘ ν΄λΉ νλλ‘ μν λ μμ
μ μ€μ λ‘ μμ scope
λμ§ μμΌλ―λ‘ μ€λ₯κ° λ°μνμ§ μμ΅λλ€.
4. @unutbuκ° μ§μ νλ―μ΄ λμμ κ° λ³μλ₯Ό λ°°μ΄ ( x = [0]
) λ‘ μ μ νκ³ μ²« λ²μ§Έ μμ ( x[0] += 1
)λ₯Ό μμ νλ κ² μ
λλ€. x
μ체 μμ λμ§ μμκΈ° λλ¬Έμ μ€λ₯κ° λ€μ λ°μ νμ§ μμ΅λλ€.
5. @raxacoricofallapatoriusμ μν΄ μ μμΌλ‘, λΉμ μ λ§λ€ μ x
μ μμ±μcounter
def initCounter ():
def counter():
counter.x += 1
print counter.x
counter.x = 0
return counter
λ΅λ³
νμ΄μ¬ 2μλ ν΄λ‘μ κ° μμμ΅λλ€ . ν΄λ‘μ μ λΉμ·ν ν΄κ²° λ°©λ²μ΄μμμ΅λλ€ .
μ΄λ―Έ μ£Όμ΄μ§ λ΅λ³μλ λ΄λΆ ν¨μμ λ³μλ₯Ό 볡μ¬νκ±°λ λ΄λΆ ν¨μμ κ°μ²΄λ₯Ό μμ νλ λ±μ λ§μ μμ κ° μμ΅λλ€.
Python 3μμ μ§μμλ³΄λ€ λͺ ννκ³ κ°κ²°ν©λλ€.
def closure():
count = 0
def inner():
nonlocal count
count += 1
print(count)
return inner
μ©λ²:
start = closure()
start() # prints 1
start() # prints 2
start() # prints 3
nonlocal
ν€μλλ₯Ό κ°μΈλ ν¨κ³Όμ λͺ
μ μ μΈκΈ μΈλΆ λ³μ λ΄λΆ κΈ°λ₯μ κ²°ν©νλ€. λ°λΌμλ³΄λ€ λͺ
ννκ² βνμβμ
λλ€.
λ΅λ³
λ³λμ μꡬ λ€μ μ€νμ΄μ€κ° νμν μν©μ΄μμμ΅λλ€. λλ μμ μ μ¬μ©νλ€. λλ κ·Έλ μ§ μλ€. λΆλ¦¬λμμ§λ§ μꡬμ μΈ μ΄λ¦μ νμμ λλ€.
>>> class f2:
... def __init__(self):
... self.a = 0
... def __call__(self, arg):
... self.a += arg
... return(self.a)
...
>>> f=f2()
>>> f(2)
2
>>> f(2)
4
>>> f(4)
8
>>> f(8)
16
# **OR**
>>> f=f2() # **re-initialize**
>>> f(f(f(f(2)))) # **nested**
16
# handy in list comprehensions to accumulate values
>>> [f(i) for f in [f2()] for i in [2,2,4,8]][-1]
16
λ΅λ³
def nested1(num1):
print "nested1 has",num1
def nested2(num2):
print "nested2 has",num2,"and it can reach to",num1
return num1+num2 #num1 referenced for reading here
return nested2
μ 곡ν©λλ€ :
In [17]: my_func=nested1(8)
nested1 has 8
In [21]: my_func(5)
nested2 has 5 and it can reach to 8
Out[21]: 13
μ΄κ²μ ν΄λ‘μ κ° λ¬΄μμ΄λ©° μ΄λ»κ² μ¬μ©λλμ§μ λν μμ λλ€.
λ΅λ³
νμ΄μ¬κ³Ό JS μμ μ¬μ΄μ λ ββλ€λ₯Έ κ°λ¨ν λΉκ΅λ₯Ό μ 곡νκ³ μΆμ΅λλ€.
JS :
function make () {
var cl = 1;
function gett () {
console.log(cl);
}
function sett (val) {
cl = val;
}
return [gett, sett]
}
κ·Έλ¦¬κ³ μ€ν :
a = make(); g = a[0]; s = a[1];
s(2); g(); // 2
s(3); g(); // 3
νμ΄μ¬ :
def make ():
cl = 1
def gett ():
print(cl);
def sett (val):
cl = val
return gett, sett
κ·Έλ¦¬κ³ μ€ν :
g, s = make()
g() #1
s(2); g() #1
s(3); g() #1
μ΄μ : μμμ λ§μ μ¬λλ€μ΄ λ§νλ―μ΄ νμ΄μ¬μμλ λ΄λΆ λ²μμ λμΌν μ΄λ¦μ λ³μμ λμ
μ΄ μμΌλ©΄ λ΄λΆ λ²μμ μλ‘μ΄ μ°Έμ‘°κ° μμ±λ©λλ€. var
ν€μλλ‘ λͺ
μ μ μΌλ‘ μ μΈνμ§ μλ ν JSμμλ κ·Έλ μ§ μμ΅λλ€ .