[Python] global과 nonlocal


Study/Python  2019. 12. 9. 21:20

안녕하세요. 명월입니다.


이 글은 Python에서 global과 nonlocal에 대한 글입니다.


제가 이전 글에서 클로져(closure)에 대해 설명한 적이 있습니다.

링크 - [Python] 함수(function) - 인라인 함수, callback, 람다 함수 그리고 클로져


다시 정리하면 클로져는 인라인 함수에서 함수 안이 아닌 외부에서 선언한 값을 가져오는 것을 뜻합니다.

data = "hi!!"
def example_function():
  # example_function에서는 data 변수를 선언하지 않았으나 외부에서 선언한 data를 사용할 수 있다.
  print(data)

example_function()

그러나 내부 함수에서 data의 값을 바꾸는 건 어떨까요?

data = "hi!!"
def example_function():
  # 외부 data의 변수 값을 수정하고 싶다!!
  data = "hello"

example_function()
print(data)

값이 변경되지 않습니다. 이유는 example_function에서 선언하는 것은 전역 data의 값이 아니고 내부 변수 data로 인식을 해서 새로 값을 선언하기 때문입니다.

그렇다면 사양에 따라 전역 변수를 함수에서 변경이 필요할 때도 있는데, 이때는 global 키워드를 사용하면 해결할 수 있습니다.

data = "hi!!"
def example_function():
  # 외부 data 변수를 함수 내부에서도 사용할 수 있게 바꾸었다.
  global data
  data = "hello"

example_function()
print(data)

example_function 내부에서 data의 값을 hello 로 바꾸었는데, 외부에서 print(data)를 실행하니 바뀐 값이 나옵니다.


이번에는 인라인 함수에서 적용해 보겠습니다.

data = "global hi!!"
def example_function():
  data = "hi!!"
  def inline_function():
    # 여기서 가장 가까운 data는 example_function의 데이터이다.
    print(data)
  inline_function()

example_function()

위는 전역 변수로 data가 있고 example_function 안에도 data가 있습니다. inline_function에서는 data를 참조하면, inline_function위치에서 가장 가까운 변수(?)를 참조하게 되어있습니다.

전역 변수보다는 example_function의 변수를 더 가깝게 생각하는 것입니다.

여기에도 inline_function에 global를 사용하면 전역 변수를 사용할 수 있습니다.

data = "global hi!!"
def example_function():
  data = "hi!!"
  def inline_function():
    # global를 선언하면 example_function이 아닌 전역 변수를 사용하게 된다.
    global data
    print(data)
  inline_function()

example_function()

그렇다면 아까 예제 처럼 inline_function안에서 global 값은 수정할 수 있을 것 같습니다. global data 하고 data = "변경 값"을 넣으면 수정이 되겠네요.

그럼, example_function의 변수는 어떻게 수정할까요? 단순히 data = "데이터" 를 넣으면 처음 예제처럼 data는 local 변수로 지정해 버립니다.


이 때는 nonlocal 키워드로 example_function 함수의 data를 수정 할 수 있습니다.

data = "global hi!!"
def example_function():
  data = "hi!!"
  def inline_function():
    # nonlocal를 사용하면 example_function의 data를 가르키게 된다.
    nonlocal data
    data = "hello"
  inline_function()
  print(data)

example_function()

그렇다면 여기서 인라인 함수 안에 인라인 함수 안의 값에서 가장 위의 변수를 수정하려면 어떻게 할까요?

data = "global hi!!"
def example_function():
  # 여기의 변수를 수정하고 싶습니다.
  data = "hi!!"
  def inline_function():
    data = "third?"
    def inline2_function():
      # nonlocal은 inline_function의 data를 가르킨다.
      nonlocal data
      data = "hello"
    inline2_function()
  inline_function()
  print(data)

example_function()

아쉽게도 여기서는 지정할 수 없네요.(어디까지 참조하길 바라는 건가?)

사실 인라인 안에 인라인 함수까지 가는 경우는 프로그램 설계를 다시 생각해 봐야 할 단계 일듯 싶습니다. 가독성이 아주 엄청 떨어지거든요..


여기까지 Python에서 global과 nonlocal에 대한 설명이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.