Python 기초

지역 변수와 전역 변수

지역 변수와 전역 변수

파이썬에서는 지역 변수와 전역 변수가 있습니다. 지역 변수는 함수 안에서 선언된 변수이고 전역 변수는 함수의 외부에서 선언된 변수입니다.

위의 그림에서 함수 안에 있는 도형은 지역 변수이고, 함수 밖에 있는 도형은 전역 변수입니다.

 

지역 변수

함수 안에 정의된 변수는 지역 변수(local variable)이라고 불리며 함수 안에서만 사용할 수 있습니다.

지역 변수는 함수가 호출될 때 생성되고 함수 호출이 종료되면 소멸되어서 더 이상 사용할 수 없습니다. 이것을 변수의 영역(scope)이라고 부릅니다.

 

함수 sub를 작성하여 봅시다.

def sub():
	s = "바나나가 좋음!"
	print(s)

sub()

 

<실행 결과>

바나나가 좋음!

 

변수 s는 sub() 함수 안에서만 사용할 수 있으며 함수 호출이 끝나면 사라집니다.

지역 변수 s의 값을 함수 외부에서 출력할 수 있을까요? 다음과 같이 print(s) 문장을 맨 끝에 추가하고 실행하여 봅시다.

def sub():
	s = "바나나가 좋음!"
	print(s)

sub()
print(s)

 

<실행 결과>

NameError: name 's' is not defined

 

오류가 발생하는 것을 알 수 있습니다. 지역 변수가 선언된 함수를 벗어나서 사용할 수는 없습니다.

지역 변수는 선언된 함수 안에서만 사용이 가능합니다. 또 함수가 끝나면 자동으로 소멸됩니다.

 

전역 변수

함수의 외부에 정의된 변수를 전역 변수(global variable)이라고 합니다. 파이썬이 전역 변수를 다루는 방식은 다른 언어와 아주 다릅니다.

파이썬에서는 다른 이야기가 없으면 함수 안에서 선언된 변수들은 무조건 지역 변수입니다. 이러한 접근 방식은 좋은 프로그래밍 습관을 장려하기 위해서입니다.

전역 변수를 사용하는 것은 좋지 않으며, 함수에 값을 전달할 때는 매개 변수를 사용하거나 함수의 반환 값을 이용하여야 합니다.

 

파이썬 함수 안에서 어떻게 전역 변수를 사용하는지를 아래 예제에서 살펴보겠습니다.

def sub():
	print(s)

s = "사과가 좋음!"
sub()

 

<실행 결과>

사과가 좋음!

 

위의 코드에서 s는 함수의 외부에 정의된 전역 변수입니다. sub() 함수를 호출하기 전에 정의되었습니다.

함수 sub()는 호출되기 전에는 실행되지 않습니다. 함수 sub() 안에는 print() 호출 문장만 있습니다.

지역 변수를 선언하는 문장이 없으니 전역 변수 s가 사용됩니다.

 

만약 우리가 함수 내부에서 전역 변수 s의 값을 변경하면 어떻게 될까요? 전역 변수 s의 값이 변경될까요? 아래의 코드를 작성하여 실행해봅시다.

def sub():
	s = "바나나가 좋음!"
	print(s)

s = "사과가 좋음!"
sub()
print(s)

 

<실행 결과>

바나나가 좋음!
사과가 좋음!

 

우리가 함수의 내부에서 변수 s에 값을 저장하면 파이썬은 우리가 지연 변수 s를 정의한 것으로 생각합니다. 따라서 전역 변수 s가 아닌 것입니다.

다시 한 번 파이썬의 원칙을 되새겨봅시다. 함수 안에서 변수에 어떤 값을 저장하면 무조건 지역 변수로 간주합니다. 기본은 지역 변수입니다.

 

아래와 같이 함수 안에서 변수 s의 값을 출력한 후에 변수 s의 값을 변경하면 어떻게 될까요?

def sub():
	print(s)
	s = "바나나가 좋음!"
	print(s)

s = "사과가 좋음!"
sub()
print(s)

 

<실행 결과>

UnboundLocalError: local variable 's' referenced before assignment

 

이때는 오류가 발생합니다. 함수 안에서 하나의 변수가 전역 변수도 되었다가 지역 변수도 될 수는 없는 것입니다.

만약 함수 안에서 전역 변수의 값을 변경해야 되겠다면 global 키워드를 사용하여 전역 변수를 사용하겠다고 파이썬 인터프리터에게 알려주어야 합니다.

def sub():
	global s		# 함수 안에서 전역 변수 s를 사용하겠다는 의미입니다.
	print(s)
	s = "바나나가 좋음!"	# 전역 변수가 변경됩니다.
	print(s)

s = "사과가 좋음!"
sub()
print(s)

 

<실행 결과>

사과가 좋음!
바나나가 좋음!
바나나가 좋음!

 

이번 코드에서는 모든 문제가 해결되었습니다. global 키워드를 사용하여 전역 변수의 값을 함수 안에서 변경할 수 있었습니다.

global을 사용하지 않고 파이썬의 함수 안에서 변수에 값을 저장하면 기본적으로 지역 변수가 됩니다.

또 변수는 선언 이후에만 사용할 수 있습니다. 파이썬에서는 변수에 값을 할당하는 순간 변수가 선언됩니다.

 

아래의 예제는 지역 변수와 전역 변수를 섞어서 작성한 프로그램입니다.

def sub(x, y):		# 함수의 매개 변수도 지역 변수의 일종입니다.
	global a	# 함수 안에서 전역 변수 a를 사용하겠다는 의미입니다.
	a = 7
	x, y = y, x
	b = 3
	print(a, b, x, y)

a, b, x, y = 1, 2, 3, 4
sub(x, y)
print(a, b, x, y)

 

<실행 결과>

7 3 4 3
7 2 3 4

 

 

도전 과제

1. 함수가 외부로부터 값을 전달받는데 사용하는 매개변수도 일종의 지역 변수입니다. 매개변수의 값을 함수 안에서 변경하면 어떻게 될까요?

아래의 프로그램 실행 결과를 미리 예측해본 후 프로그램을 실행시켜 결과가 일치하는지 확인해봅시다.

# 함수가 정의됩니다.
def sub(mylist):
	# 리스트가 함수로 전달됩니다.
	mylist = [1, 2, 3, 4]	# 새로운 리스트가 매개변수로 할당됩니다.
	print("함수 내부에서의 mylist :", mylist)
	return

# 여기서 sub() 함수를 호출합니다.
mylist = [10, 20, 30, 40]
sub(mylist)
print("함수 외부에서의 mylist :", mylist)

 


2. 우리가 함수의 외부에서 변수를 정의하면, 이 변수는 모든 함수에서 사용이 가능한 전역 변수가 됩니다.

일반적으로 전역변수는 디버깅을 어렵게 하고 프로그램의 복잡도를 증가시키기 때문에 사용하지 않는 것이 좋습니다.

모든 변수는 함수 안에 정의하는 것이 좋으나 상수를 정의할 때는 예외입니다.

상수는 고정된 값을 가지고 각 함수마다 상수를 정의하게 되면 공간의 낭비가 심해지기 때문입니다.

파이를 전역 변수로 선언하고 이것을 이용하여 원의 면적과 둘레를 계산하는 함수를 작성해봅시다.

 

<실행 결과>

원의 반지름을 입력하세요 : 10
원의 면적 : 314.159265358979
원의 둘레 : 62.8318530717958