Python 변수 정리: 지역변수, 전역변수, global, 클래스 변수
목차
1. 지역변수 vs 전역변수
Python에서 변수는 어디에서 선언되었는지에 따라 사용 가능한 범위(Scope)가 결정됩니다.
이 범위에 따라 변수는 전역변수(Global Variable)와 지역변수(Local Variable)로 나뉘며, 각각 다음과 같은 특징이 있습니다.
◆ 전역변수(Global Variable)
- 함수 외부에서 선언된 변수입니다.
- 해당 모듈(파일) 전체에서 어디서든 접근할 수 있습니다.
- 다른 함수나 블록에서도 읽기(read)**는 자유롭게 가능하지만, 수정(write)하려면 global 키워드가 필요합니다.
◆ 지역변수(Local Variable)
- 함수 내부에서 선언된 변수입니다.
- 함수 실행 중에만 메모리에 존재하며, 함수가 끝나면 자동으로 사라집니다.
- 함수 외부에서는 절대 접근할 수 없습니다.
◆ 예제 코드
x = 10 # 전역변수
def func():
y = 5 # 지역변수
print("함수 내부 출력:", x, y) # 전역변수 x와 지역변수 y 모두 접근 가능
func()
print("함수 외부 출력:", x) # 전역변수 x는 함수 밖에서도 사용 가능
print("함수 외부 출력:", y) # ❌ 오류 발생: y는 func 함수 내부에서만 존재
출력결과:
함수 내부 출력: 10 5
함수 외부 출력: 10
NameError: name 'y' is not defined
2. global 키워드의 역할과 주의사항
Python에서 함수 내부에서 전역변수(global variable)를 수정하려 할 때는 반드시 global 키워드를 사용해야 합니다.
그렇지 않으면 예상치 못한 오류가 발생하게 됩니다.
◆ 전역변수는 읽기만 하면 global 없이도 가능
counter = 0
def show():
print("counter =", counter) # 전역변수 읽기만 함
show() # 출력: counter = 0
이처럼 전역변수를 읽기만 하는 경우에는 문제가 전혀 없습니다.
Python은 이 상황에서 counter가 전역변수임을 자동으로 인식합니다.
◆ 전역변수를 수정하려고 하면 오류가 발생
counter = 0
def increment():
counter += 1 # ❌ 오류 발생
increment()
UnboundLocalError: cannot access local variable 'counter' where it is not associated with a value 오류가 발생합니다.
Python은 함수 내부에서 counter += 1 같은 대입(assign) 문이 등장하면, 그 이름의 변수를 "지역변수"로 간주합니다.
하지만 지역변수 counter는 아직 선언되지 않았으므로, 그 값을 참조하는 counter += 1에서 오류가 나는 것입니다.
◆ 전역변수를 수정하려고 global 키워드 사용
counter = 0
def increment():
global counter # 전역변수를 명시적으로 사용하겠다고 선언
counter += 1
increment()
print(counter) # 출력: 1
◆ 함수 내부에서 전역변수와 같은 이름의 변수를 사용하면:
value = 100
def change():
value = 200 # 지역변수로 새롭게 생성됨
print("함수 내부 value:", value)
change()
print("함수 외부 value:", value) # 여전히 100
여기서 value = 200은 전역변수 value를 바꾸는 것이 아니라, 함수 안에서만 존재하는 지역변수를 새로 만든 것입니다.
3. nonlocal 키워드
nonlocal은 중첩 함수 내부에서 바로 바깥 함수의 지역변수에 접근하여 값을 수정할 수 있게 해주는 키워드입니다.
전역(global) 변수에는 사용할 수 없습니다. 그럴 땐 global을 사용해야 합니다.
def outer():
value = 10 # 외부 함수의 지역변수
def inner():
nonlocal value # 바깥 함수의 지역변수 'value'를 참조하겠다고 명시
value += 5 # 실제로 바깥 변수 값을 수정
inner()
print(value) # 15
Python은 기본적으로 함수 안에서 변수에 값을 대입하면, 그 변수를 지역변수(Local Variable)로 취급합니다.
그래서 내부 함수에서 바깥 함수의 지역변수를 수정하려고 하면,
오히려 내부 함수의 새로운 지역변수를 만들어버려 의도한 결과가 나오지 않습니다.
nonlocal 없이 했을 때의 문제
def outer():
value = 10
def inner():
value = value + 5 # ❌ 오류 발생
inner()
print(value)
UnboundLocalError: cannot access local variable 'value' where it is not associated with a value 오류 발생
Python은 value = value + 5를 보고 "이건 inner() 안에서 선언된 지역변수 value에 값을 할당하려는 거구나" 라고 해석합니다.
하지만 초기화된 값이 없기 때문에 참조(reference) 시점에서 오류가 발생하는 것입니다.
4. 변수처럼 다루는 함수-일급객체로서의 함수
Python에서 함수는 일급 객체(First-class object)입니다.
즉, 함수를 변수에 할당하고, 다른 함수에 인자로 전달하거나, 함수에서 리턴값으로 반환할 수 있습니다.
이것은 Python이 **함수를 값(value)**처럼 다루기 때문에 가능한 일입니다.
◆ 일급 객체란?
"일급 객체"란, 다음 조건들을 만족하는 데이터입니다:
- 변수에 할당 가능
- 함수의 인자로 전달 가능
- 함수의 리턴값으로 사용 가능
- 자료구조(리스트, 딕셔너리 등)에 저장 가능
◆ 변수에 함수 할당하기
def greet():
return "Hi"
say_hello = greet # greet 함수 객체를 say_hello에 할당
print(say_hello()) # 출력: Hi
say_hello는 greet 함수를 가리키는 변수입니다.
say_hello()는 결국 greet()와 동일하게 작동합니다.
◆ 함수 인자로 전달하기
def run_function(func):
print("함수 실행 결과:", func())
def greet():
return "안녕하세요"
run_function(greet) # greet 함수 자체를 인자로 전달
여기서 func()는 전달받은 함수 greet()를 실행합니다.
◆ 함수에서 함수 반환하기(클로저)
def make_multiplier(n):
def multiplier(x):
return x * n
return multiplier
times3 = make_multiplier(3)
print(times3(5)) # 출력: 15
make_multiplier(3)은 n = 3을 기억하는 함수를 반환합니다.
이런 함수는 클로저(closure)라고 부릅니다.
이처럼 함수를 리턴값으로 반환하는 것도 가능합니다.
◆ 함수들을 리스트나 딕셔너리에 저장
def add(x, y): return x + y
def sub(x, y): return x - y
ops = [add, sub]
print(ops[0](10, 3)) # 13
op_map = {"+": add, "-": sub}
print(op_map["+"](7, 5)) # 12
함수가 리스트, 딕셔너리 같은 컨테이너에 저장되고, 나중에 꺼내서 실행 가능
5. 클래스 변수 vs 인스턴스 변수
Python 클래스 내부의 변수는 선언 위치와 사용 방법에 따라 3가지 종류로 나뉩니다:
구분 | 선언위치 | 접근방법 | 특징 |
클래스 변수 | 클래스 정의 블록 내부 | 클래스이름.변수, self.변수 | 모든 인스턴스가 공유하는 변수 |
인스턴스 변수 | __init__() 또는 메서드 내부 | self.변수 | 각 인스턴스마다 독립적인 값 가짐 |
지역 변수 | 메서드 내부 | 메서드 내부에서만 사용 | 함수/메서드가 실행될 때만 생성, 종료 시 사라짐 |
class Dog:
species = "Canine" # ✅ 클래스 변수
def __init__(self, name):
self.name = name # ✅ 인스턴스 변수
def bark(self):
sound = "Woof!" # ✅ 지역 변수
return f"{self.name} says {sound}"
dog1 = Dog("Buddy")
dog2 = Dog("Charlie")
print(dog1.species) # Canine (클래스 변수)
print(dog1.name) # Buddy (인스턴스 변수)
print(dog1.bark()) # Buddy says Woof! (지역 변수 사용)
- dog1.species는 클래스 전체에서 공유되는 값 "Canine"을 참조합니다.
- dog1.name은 Buddy, dog2.name은 Charlie처럼 각각의 인스턴스에 따라 다르게 설정됩니다.
- bark() 내부의 sound는 지역 변수로, 함수가 실행될 때만 존재합니다.
◆ 주의 사항: mutable 한 클래스 변수의 공유
클래스 변수는 모든 인스턴스에서 공통으로 공유되기 때문에,
list, dict 같은 변경 가능한 객체를 클래스 변수로 선언하면 의도치 않은 결과가 발생할 수 있습니다.
잘못된 예시:
class MyClass:
items = [] # 클래스 변수 (mutable)
def add_item(self, item):
self.items.append(item)
a = MyClass()
b = MyClass()
a.add_item("apple")
b.add_item("banana")
print(a.items) # ['apple', 'banana']
print(b.items) # ['apple', 'banana'] (같은 객체!)
- 모든 인스턴스가 동일한 리스트 객체를 공유하고 있기 때문에, 한 인스턴스의 변경이 다른 인스턴스에도 영향을 줍니다.
해결 방법: 인스턴스 변수로 선언:
class MyClass:
def __init__(self):
self.items = [] # 인스턴스마다 별도의 리스트 생성
def add_item(self, item):
self.items.append(item)
- 이제 self.items는 인스턴스마다 독립적으로 존재하므로 문제가 없습니다.
관련 글 링크
[1.시스템&인프라/개발환경] - VSCode에서 Python 가상환경(.venv) 설정 및 여러 버전 관리하기
VSCode에서 Python 가상환경(.venv) 설정 및 여러 버전 관리하기
Python 프로젝트를 진행하다 보면, 프로젝트별로 다른 Python 버전과 패키지를 사용하는 경우가 많습니다. 이 글에서는 포터블 버전의 Python과 Visual Studio Code를 활용하여 여러 버전의 Python 가상환경(
quadcube.tistory.com
[1.시스템&인프라/개발환경] - Windows에서 VSCode Portable Python 개발 환경 만들기
Windows에서 VSCode Portable Python 개발 환경 만들기
이 글에서는 포터블 Python과 Visual Studio Code를 하나의 폴더에 구성하여, 어디서든 동일한 개발 환경을 활용할 수 있는 방법을 소개합니다. Windows에서 VSCode Portable Python 개발 환경 만들기 목차 1. 포
quadcube.tistory.com
'3.개발언어&라이브러리 > Python' 카테고리의 다른 글
6. Python 병렬 처리 : GIL, threading, asyncio, multiprocessing (0) | 2025.05.22 |
---|---|
5. Python 예외(Exception) 처리 : try-except-finally, with (0) | 2025.05.22 |
4. Python 함수구조, 함수인자, 람다함수, 클로저, 고차함수, 데코레이터 (0) | 2025.05.22 |
3. Python 클래스 정리: 클래스, 상속, 메서드, 접근제어 (0) | 2025.05.21 |
1. Python 모듈, 패키지, import 개념 정리: __init__.py (0) | 2025.05.20 |