변수명, 함수명, 클래스명 등 이름(name)이 사용될 수 있는 영역을 Scope라고 합니다. 즉, 변수가 살아있는 범위와 이를 어디에서 사용할 수 있는지에 대한 규칙입니다.
함수 바깥에서 선언한 변수로, 스크립트 전체에서 접근할 수 있습니다.
x = 10 # 전역 변수
def foo():
print(x) # 함수 안에서도 전역변수 '읽기' 동작 가능
foo()
print(x)
함수 안에서 선언된 변수는 해당 함수 내부에서만 접근 가능하며, 함수 종료(리턴)와 함께 소멸합니다.
def foo():
y = 10 # y는 foo의 지역변수
print(y)
foo()
# print(y) # 에러 발생: 함수 밖에서는 지역 변수에 접근 불가
함수 내에서 전역 변수와 동일한 이름에 값을 대입하면, 파이썬은 이를 새로운 지역 변수로 간주합니다.
z = 10
def foo():
z = 20 # z는 foo의 지역변수로 새로 생성됨 (쓰기 동작)
print(z) # 지역변수 z(20) 출력
foo() # 20
print(z) # 10 (전역 변수는 변하지 않음)
함수 내에서 변수에 값을 대입하는 코드가 있으면 파이썬은 그 변수를 지역 변수로 인지합니다. 대입 전에 사용하려고 하면 에러가 발생합니다.
a = 1
def foo():
# a = a + 1 # 에러 발생: a를 지역 변수로 인식했지만 값이 할당되기 전임
print('foo] a=', a)
가장 깔끔하고 구조적인 방법입니다.
a = 1 # 전역변수
def foo(a): # 매개변수 a (지역변수)
a = a + 1
return a
a = foo(a) # 리턴값으로 전역변수 a를 갱신
print('전역 a=', a)
코드의 의존성을 높여 유지보수를 어렵게 만들 수 있습니다.
a = 1
def foo():
global a # 이 함수 안에서 사용하는 a는 전역변수임을 선언
a = a + 1
print('foo] a=', a)
foo()
print('전역 a=', a)
네임스페이스는 '이름'들이 담겨있는 공간입니다. locals()를 통해 확인할 수 있습니다.
이름을 찾을 때 L → E → G → B 순서로 탐색합니다.
k = 100 //Global
def aaa():
k = 200 # Enclosing scope가 됨
print(k) # Local
def bbb():
# k를 찾을 때: L(없음) -> E(여기 있네!)
print(k)
bbb()
aaa()
#출력 결과
200
200
Python은 if, for, while, try, with 블록에서 새로운 Scope를 생성하지 않습니다.
Java나 C, JavaScript(let, const)와는 대조적인 특징입니다. 블록 안에서 선언한 변수도 블록 밖(동일 함수 내 또는 전역)에서 사용 가능합니다.
# for문 예시
for i in range(3):
xx = i * 10 # xx는 전역 scope에 생성됨
print(xx) # for 바깥에서도 사용 가능 (20 출력)
# if문 예시
if True:
yy = 100
print(yy) # 사용 가능
def(함수), lambda, classif, for, while, try-except, with중첩 함수에서 바깥 함수의 변수를 수정하고 싶을 때 사용합니다.
k = 100
def aaa():
k = 200
print("aaa 내부 k:", k)
def bbb():
nonlocal k # bbb의 지역변수가 아니라 aaa의 k를 사용하겠다고 선언
k = k + 1
print("bbb 내부 k:", k)
bbb()
print("bbb 호출 후 aaa의 k:", k)
aaa()
print("전역 k:", k)