Programming Language/Python

Nested function, Nonlocal, Global

test22 2024. 4. 2. 21:45

Nested function

Nested function(중첩 함수)는 함수 안에 함수를 가리킨다.

 

즉, 다음과 같은 형태로 함수를 정의한다면

def outer_function(a):
    x=0
    def inner_function(b):
        y=1
        
    inner_function(0)

 

outer_function에 감싸진 inner_function을 가리켜 nested function라고 부른다.

 

이러한 중첩 함수는 outer_function 내에서만 다룰 수 있고 그 바깥에서는 호출할 수가 없다. 그렇기 때문에 함수 내부에서 간단하게 사용될 정도로 쓴다면 가독성을 좋게 만들 수 있다. 다만 중첩 함수의 코드가 길어진다면 가독성이 안 좋아질 수 있다.

 

outer_function 바깥에서도 자주 사용될 수 있는 코드라면 일반적인 함수로 만들어 사용하는 것이 낫다.

 

Nested function의 특징

inner_function에서 outer_function의 변수를 사용할 수 있다.

def outer_function(a):
    x=0
    def inner_function(b):
        y=1
        print(x)
        
    inner_function(0)

 

가령 위 코드와 같이 inner_function에서 outer_function의 x 변수를 출력하도록 할 수 있다.

 

다만, 주의할 점이 있는데 기본적으로 읽기만 가능하다. 즉, outer_function의 변수 값을 읽어볼 순 있어도 수정을 가할 수가 없다. 만약 위 코드에서  inner_function 내에 x+=1 등의 코드가 한 줄이라도 있다면  inner_function을 호출할 때 에러가 난다.

 

Nonlocal

inner_function에서 outer_function의 변수를 수정하려고 하면 에러가 난다고 하였다. 하지만 특정 키워드를 추가하면 수정까지 할 수 있는데 그것이 바로 nonlocal 키워드이다. 단어 그대로 local이 아님을 의미한다. 그렇다고 해서 global인 것은 아니므로 유의해야 한다.

 

def outer_function(a):
    x=0
    def inner_function(b):
        nonlocal x
        y=1
        x+=1
        print(x)
        
    inner_function(0)

위 코드처럼 inner_function 내에 nonlocal 키워드를 사용한다면 outer_function의 변수 값을 수정할 수 있게 된다.

 

그렇다면 중첩 함수가 여러 개 일땐 어떻게 될까?

def outer_function(a):
    x=0
    def inner_function1(b):
        y=1
        def inner_function2(c):
            z=2
            def inner_function3(d):
                nonlocal x,y,z
                z+=1
                y+=1
                x+=1
                print(x,y,z)
               
            inner_function3(0)
        inner_function2(0)
    inner_function1(0)

위 코드처럼 중첩 함수를 깊게 중첩시킨 코드를 작성할 수 있다. 여기서 inner_function3처럼 역시나 nonlocal 키워드를 쓴다면 inner_function3를 감싸는 바깥 함수들의 변수 값들을 전부 수정해볼 수 있다.

 

당연하지만 함수의 바깥에서는 함수 내부를 볼 수 없기 때문에 상대적으로 바깥인 함수에서 안 쪽 함수에 정의된 지역 변수는 처리할 수 없다.

 

Global

앞에선 중첩 함수 내 지역 변수들을 nonlocal 키워드를 이용해 처리하는 법을 다뤘다. 여기서 더 나아가 아예 함수에 포함되어 있지 않은 변수 즉, 전역 변수를 다루고자 한다면 어떻게 해야 할까? 전역 변수도 마찬가지로 수 내에서 기본적으로 읽기만 가능하고 수정이 불가능하다. 하지만 global 키워드를 사용한다면 nonlocal 키워드를 사용할 때랑 똑같이 전역 변수들을 함수 내에서 처리할 수 있게 된. 

n = 0

def f():
    n += 100
    print(n)

가령 위 코드처럼 전역 변수를 함수 내에서 바로 수정을 가한다면 에러가 뜬다.

 

위 코드에서 함수 내에 global 키워드를 사용한다면

n = 0

def f():
    global n
    n += 100
    print(n)

f 내에서 전역 변수인 n의 값을 수정할 수 있게 되고 이때 f를 호출한다면 정상적으로 100을 출력하게 된다.

 

 

 

결론

이처럼 중첩 함수와 지역 변수, 전역 변수 다루는 법을 알아보았다. 각 변수들이 정의된 위치에 따라 scope와 namespace가 각각 다르기 때문에 nonlocal 및 global 키워드를 적절히 사용하는 것이 중요하다.