State Retention Compare
Module scope State Retention
def tester(start) :
global state
state = start
def nested(label) :
print(label , state)
state +=1
return nested
F = tester(0)
F('spam')
F('ham')
G = tester(42)
module scope의 state에 보관하게 되면 이 state를 담고 있는 variable은 global variable이 되게 됩니다 . 이렇게 global state를 사용하게 되면 아래와 같은 문제점이 발생합니다.
global
declaration이 모든 코드 블록(ex. fucntion,class) 에 적용이 되어야 한다.- module namespace에 name collision의 가능성이 있다.
- 1개의 name으로 같은 state만 보관이 가능하다.
3번째 특성이 제일 중요한 특성입니다. MultiProcessing에서 , fork된 processe들이 같은 공유 resource(ex.lock,mutex) 를 가지게 하기위해 의도적으로 사용할 수 있는 중요한 기능이 될 수도 있습니다. 하지만, 여러개의 event handler를 만들어야 할 경우에는 적합한 option이 아닙니다 .
Global Statement를 사용할 때는, cross-file change, control flow 등 여러가지 option등을 고려해야 합니다 .
참조 : Python Global Statement and Gloal scope is dangerous - Woongjoon_AI (woongjoonchoi.github.io)
Enclosing Function scope name Retention
위의 global state를 사용하게 되면 아래와 같은 문제점들이 있었습니다.
- function이 값을 return 하지만, 각 call 사이에서 state들이 보존되어 전달되지 않는다.
- 대부분의 application들이 각기 다른 state들을 가지길 원한다.
def tester(start) :
state = start
def nested(label) :
nonlocal state
print(label , state)
state +=1
return nested
F = tester(0)
F('spam')
F('ham')
G = tester(42)
nonlocal
은 변경이 가능한 독립적인 state들을 메모리에 저장하게 됩니다. 이는 다음과 같은 상황에서 사용합니다.
global
을 사용할 수 없을 때- class를 사용하는 것이 너무 overkill 일 때
NonLocal을 사용할 때에는 global과는 유사하지만, 차이점이 있으므로 이를 잘 인지하면서 사용해야 합니다. 그리고, enclosing function scope에 있는 name을 reference하는것만 필요하다면 factory(closure) function을 사용하는 것도 하나의 선택지가 될 수 있다.
참조 : Nonlocal statement - Woongjoon_AI (woongjoonchoi.github.io)
참조 : How to state retention in nested scope - Woongjoon_AI (woongjoonchoi.github.io)
Class State Retention
class의 member 를 이용해서 state를 보존할 수도 있습니다. class를 사용하면 아래와 같은 기능을 사용할 수 있습니다
- inheritance
- method
- etc..
class의 member는 explicit하게 access 할 수 있는 반면 , nested function을 이용해서 enclosing function scope에 state를 보존하면 implicit하게 access 할 수 있습니다 .
class로 이러한 state 문제를 해결할 수 있지만, 단순히 state 1개를 보존하기 위해서 class를 사용하는 것은 overkill이라 볼 수 있습니다.
Function Attribute
Python에서 Functoin attribute를 사용하면 2.X, 3.X에서도 nested function에 function attribute를 추가하게 됩니다.
def tester(start) :
def nested(label) :
print(label , state)
state +=1
nested.state = start
return nested
F = tester(0)
F('spam')
F('ham')
G = tester(42)
마치 class attribute처럼 어디서든 이 attribute에 access할 수 있게 됩니다 . 이는 nonlocal scope에 name을 할당하는 것이 아닌 , nested라는 function object에 attribute를 추가하는 것입니다.
하지만, 이 기능은 nonlocal같은 비교적 최신 기능과 많이 중복되는 부분이 있는 오래된 구식 유물이라 생각이 듭니다 .
mutable in function
def tester(start):
def nested(label):
print(label, state[0]) # Leverage in-place mutable change
state[0] += 1 # Extra syntax, deep magic?
state = [start]
return nested
Python에서는 이러한 syntax가 허용이 됩니다. enclosing scope에서 mutable object를 변경이 가능합니다 . 하지만 , 이는 보는 사람에게 혼란을 줄 수 있는 syntax로 이런식으로 작성을 하는 것은 피해야 합니다 .
그저 legacy 코드에서 이러한 코드를 보게 된다면 어떤 동작을 하는 지 정도만 이해하면 됩니다 .
Leave a comment