본문 바로가기

[내일배움캠프]스파르타코딩클럽 AI 웹개발/Today I Learned

[TIL] global과 nonlocal with python

프로그래머스의 코딩테스트 문제 난이도가 올라가면서 함수 안에 함수를 작성하는 일이 생기기도 한다

이때 global 변수를 선언해야 할 지 nonlocal 변수를 선언해야 할 지, 그리고 어떻게 변수를 사용할 지에 대한 의문점이 많이 들었다.

오늘은 이에 대한 의문점을 해소하고자 한다

 

 

 

 

먼저 global과 nonlocal은 변수의 범위에 대한 개념을 알고 있어야 한다. 변수의 범위는 변수를 어디에 선언하는지에 따라 그 범위가 결정된다. 함수 내부에서 선언된 변수는 함수 내부에서만 유효하게되는 변수이다. 이때의 변수를 지역(local)변수라고 한다. 그리고 함수의 외부 지역에서 선언된 변수가 전역(global)변수가 된다.

그렇다면 nonlocal은 언제 사용되는 것인가? nonlocal 변수, 즉 비지역 변수는 함수를 중첩했을 때 나타나는 지역이다. 내부 함수와 외부 함수가 있을 때 외부 함수 내, 그리고 내부함수 외의 지역은 내부함수의 입장에서 비지역 함수가 되는 것이다.

 

# A함수와 B함수의 global(전역) 범위
def A():
    # A 함수의 local(지역) 범위
    # B 함수의 nonlocal(비지역) 범위
    def B():
        # B 함수의 local(지역) 범위

 

 

 

 

그러면 다시 돌아와서 파이썬에서 global과 nonlocal은 어떻게 사용해야 할까?

먼저 다음과 같은 함수를 정의해보자

 

loc_g = "A와 B의 전역변수"
def A():
    loc_A = "A의 지역변수 B의 비지역변수"
    def B():
        loc_B = "B의 지역변수"

 

위의 코드에서 각각의 지역에 print문을 넣어 변수를 출력해보자

 

loc_g = 0 # A 와 B의 전역 변수
def A():
    loc_A = 1 # A의 지역 변수, B의 비지역 변수
    def B():
        loc_B = 2 # B의 지역 변수
        print(loc_g)
        print(loc_A)
        print(loc_B)

A()

 

위의 코드를 실행했을때 실제 콘솔창에는 아무것도 출력되지 않지만 오류가 발생하지는 않는다

아무것도 출력이 되지 않는 이유도 전역 지역에서 정의된 함수가 A이고 B는 그 내부에서 정의가 되었기 때문이다.

B()를 실행하면 오류가 나는 이유도 B 함수는 A의 지역함수이기 때문이다

따라서 가장 내부에 있는 함수인 B는 전역(gobal), 비지역(nonlocal), 지역(local) 변수를 사용할 수 있다는 것을 알 수 있다

 

그러면 A의 지역에서는 어떤 변수를 사용할 수 있을까

 

loc_g = 0 # A 와 B의 전역 변수
def A():
    loc_A = 1 # A의 지역 변수, B의 비지역 변수
    def B():
        loc_B = 2 # B의 지역 변수

    print(loc_g)
    print(loc_A)
    # print(loc_B)

A()

 

 B의 지역변수인 loc_B는 사용할 수 없다. 마친가지로 전역 지역에서는 전역변수만 사용할 수 있다.

그럼 함수 내부애서 비지역 변수 혹은 지역변수를 변경해주기 위해서 global과 nonlocal을 사용할텐데 어떻게 적절하게 사용할 수 있을까?

 

var = 0
def A():
    var = 100
    def B():
        # global var
        var = 200
        print(var)
    B()
    print(var)

A()
print(var)

 

위의 코드를 실행한 결과는 다음과 같다

더보기

200

100

0

서로간에 영향을 주지 않는 변수라는 의미가 된다.

이때 global을 선언해주면 어떻게 될까

 

먼저 A함수에서 global을 선언해보자

var = 0
def A():
    global var
    var = 100
    def B():
        var = 200
    B()
    print(var)

A()
print(var)

 

위의 코드를 실행한 결과는 다음과 같다

더보기

200

100

100

A함수 안에서 선언된 global은 전역 지역에 영향을 주게 된다

그러면 B함수 안에서 global을 선언해주면 어떻게 될까

 

 

var = 0
def A():
    # global var
    var = 100
    def B():
        global var
        var = 200
        print(var)
    B()
    print(var)

A()
print(var)

 

위의 코드를 실행하면 다음과 같은 결과가 나온다

더보기

200

100

200

즉 global은 nonlocal지역에는 영향을 주지 않고 global 지역에만 영향을 준다

마지막으로 B에서 nonlocal을 선언해보자

 

var = 0
def A():
    # global var
    var = 100
    def B():
        # global var
        nonlocal var
        var = 200
        print(var)
    B()
    print(var)

A()
print(var)

 

위의 코드를 실행하면 다음과 같은 결과를 얻을 수 있다

 

더보기

200

200

0

 

nonlocal 선언시 nonlocal 지역에만 영향을 주고 global 지역에는 영향을 주지 못한다

global과 nonlocal을 모두 사용하면 충돌이 발생하며 오류 메세지가 뜨니 둘 중 상황에 맞게 사용하기를 바란다!