3.개발언어&라이브러리/Python

2. Python 변수 정리: 지역변수, 전역변수, global, 클래스 변수

쿼드큐브 2025. 5. 21. 12:22
728x90

Python 변수 정리: 지역변수, 전역변수, global, 클래스 변수

 

목차

1. 지역변수 vs 전역변수

2. global 키워드의 역할과 주의사항

3. nonlocal 키워드

4. 변수처럼 다루는 함수-일급객체로서의 함수

5. 클래스 변수 vs 인스턴스 변수

관련 글 링크

 

 

1. 지역변수 vs 전역변수

Python에서 변수는 어디에서 선언되었는지에 따라 사용 가능한 범위(Scope)가 결정됩니다.
이 범위에 따라 변수는 전역변수(Global Variable)와 지역변수(Local Variable)로 나뉘며, 각각 다음과 같은 특징이 있습니다.

출처:https://www.pythonhello.com/fundamentals/python-global-variables

 

◆ 전역변수(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)**처럼 다루기 때문에 가능한 일입니다.

 

◆ 일급 객체란?

"일급 객체"란, 다음 조건들을 만족하는 데이터입니다:

  1. 변수에 할당 가능
  2. 함수의 인자로 전달 가능
  3. 함수의 리턴값으로 사용 가능
  4. 자료구조(리스트, 딕셔너리 등)에 저장 가능

◆ 변수에 함수 할당하기

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

 

728x90