이전 글에서는 Python 함수가 단순한 코드 묶음이 아니라,
메모리 상에서 하나의 객체로 존재하며 스택/힙 구조와 함께 동작한다는 점을 정리하였다.
이번 글에서는 그 연장선으로, 함수 내부에서 자연스럽게 이어지는 개념들인
변수 범위(scope), 클로저, 콜백 함수, 람다 함수를 정리해 볼 예정이다.
1. 변수의 범위 (Scope)
변수의 범위(scope)는 “이 변수를 어디까지 사용할 수 있는가”를 결정하는 규칙이다.
Python에서는 LEGB 규칙(지역:Local → 인클로징:Enclosing → 전역:Global → 내장:Built-in) 순서로 변수를 찾는다.
즉, 변수와 함수의 이름이 같을 경우
지역변수(Local)의 우선순위가 가장 높다.
1) 지역 변수 (Local Scope)
지역변수는 함수 안에서 선언된 변수로, 해당 함수 내부에서만 사용할 수 있다.
함수가 끝나는 순간 같이 사라지는 가장 짧은 생명주기를 가진 변수라고 볼 수 있다.
def local_example():
local_var = "로컬 변수"
print(local_var)
local_example()
이 변수는 함수 외부에서 접근할 수 없다.
즉, 함수 실행 단위(스택 프레임) 안에서만 살아있는 값이다.
2) 전역 변수 (Global Scope)
전역 변수는 함수 바깥에서 선언되는 변수로, 여러 함수에서 공유하여 사용할 수 있다.
프로그램 전체에서 접근 가능한 공용 변수에 가깝다.
global_var = "I'm a global variable"
def test_global_scope():
print(global_var) # 외부 변수를 함수내에서 사용가능 : 전역변수
test_global_scope()
다만 함수 내부에서 값을 수정하고 싶을때는
별도의 선언이 추가로 필요하다.
이때 필요한 것이 바로 global 키워드이다.
💡global 키워드의 유무에 따른 차이점
global 키워드의 핵심은 간단하다.
함수 안에서 값을 새로 대입하면 기본적으로 지역 변수가 된다.
📌global 키워드가 없을 때
이 경우엔 함수 안에서 global_var = 20 을 쓰면
기존 전역 변수를 바꾸는게 아니라,
아예 새로운 지역 변수를 하나 만들게 된다.

쉽게 말하면
함수 안에서는 "내 변수를 따로 만들었네?" 라고 생각하여
함수 안에 변수와 별개로 밖에 있는 변수는 그대로 유지되는 것 이다.
📌 global 키워드를 사용했을 때
global 키워드를 사용하게 되면 이제 진짜 전역 변수를 수정할 수 있게 되는 것 이다.
여기선 global global_var2를 사용해주었기 때문에
"이 변수는 함수 밖에 있는걸 쓸게"라고 미리 말해주는 것이다.

쉽게 말하면
함수 안에서 바꿨지만 global 키워드를 통해
밖에도 그대로 영향이 가게되는것이다.
- global 없음 → 함수 안에서만 쓰는 새 변수 생성
- global 있음 → 함수 밖에 있는 진짜 변수 수정
즉, global은 이 변수는 밖에 있는걸 쓸게! 라고 선언하는 키워드라고 생각하면 쉽다.
3) 클로저 변수 (Enclosing Scope)
클로저 변수는 함수 안에 또 다른 함수가 정의되는 구조에서 발생하는 범위이다.
내부 함수가 외부 함수의 변수를 참조할 때 클로저가 형성된다.
def outer_function():
enclosing_var = "둘러싼 범위 변수"
def inner_function():
print(enclosing_var)
return inner_function
f = outer_function()
f()
위 코드에서 중요한 점은
outer_function이 끝났지만 값이 유지된다는 점이다.
💡클로저가 유지되는 이유
일반적으로 함수가 종료되면 지역 변수는 사라진다.
하지만 내부 함수가 그 변수를 참조하고 있을 경우
Python은 해당 값을 별도로 보관하게 된다.
이때 저장되는 구조가 바로 클로저 공간이다.
내부적으로는 함수 객체의 __closure__에 값이 유지되는 특징이 있다.
4) Built-in 네임스페이스
네임스페이스는 Python이 기본적으로 제공하는 함수들이 존재하는 영역을 말한다.
우리가 따로 정의하지 않아도 언제든 사용할 수 있다.
대표적으로 print(), len(), type(), range() 등이 있다.
len = 5 # built-in 함수 len을 덮어씀
print(len([1, 2, 3])) # TypeError발생
위와 같이 변수 이름을 잘못 지정할 경우 내장함수가 가려질 수 있다.
그래서 실무에선 built-in 이름을 변수로 쓰는 것을 피하여 프로그램을 만든다.
2. 함수 메모리 제거
Python에서 함수도 결국 객체이기 때문에
참조 관계에 따라 메모리에서 관리된다.
더이상 참조되지 않으면 가비지 컬렉션 대상이 된다.
def func1():
print("처음으로 만드는 함수")
del func1
del은 이름(참조)을 제거하는 동작이지,
즉시 메모리를 지워버리는 명령어는 아니다.
Python은 참조 카운트와 가비지컬렉션을 함께 사용해 객체를 관리한다.
3. 콜백 함수 (Callback Function)
콜백 함수는 다른 함수에 전달되어 필요할 때에 호출되는 함수를 말한다.
즉, 실행 시점을 나중으로 넘겨주는 구조라고 보면 이해하기 쉽다.

위 코드에서 say_hello는 즉시 실행되지 않고,
execute 내부에서 호출된다.
※ say_hello() : 지금 당장 함수를 호출
※ say_hello : 함수의 주소
※ execute(say_hello) : say_hello 함수의 주소를 execute 함수 매개변수에 넣어 실행
1) 반복 구조에서 콜백 활용하기
콜백 함수는 반복하는 구조와 동작을 분리할 때 가장 많이 사용된다.
즉, 데이터는 고정하고 로직만 교체하는 구조하는 것이다.

위 코드에서 중요하게 봐야 할 것들은 아래와 같다.
- 반복(for문) 고정
- 반복문에서 처리 할 방식만 콜백으로 변경
2) sorted()에서 콜백 사용
콜백은 실제 파이썬 함수에서도 많이 사용된다.
대표적인 예시로 sorted()의 key이다.

위 코드를 쉽게 설명하면
학생을 정렬할 때,
딕셔너리에 있는 점수를 기준으로 비교해줘 라는 함수를 넘기는 것이다.
즉, get_score가 콜백 함수 역할을 한다.
4. 람다 함수 (Lambda Function)
람다 함수는 이름 없이 한 줄로 정의하는 간단한 익명함수로
짧은 로직을 빠르게 표현할 때 주로 사용된다.
람다 함수는 메모리(Heap)에 잠시 머물렀다 사용된 후,
더 이상 쓰이지 않으면 가비지 컬렉터가 치워주는 효율적인 일회성 함수이다.
그리고 람다 함수는 무조건 return이 되는 형식이다.
lambda 매개변수: 반환할_표현식
1) 기본 사용방법
짧은 연산이라면 def 대신 람다로 간단하게 표현할 수 있다.
# 일반 함수
def square(x):
return x * x
# 람다 함수
square = lambda x: x * x
# 출력결과 둘 다 : 25
※ 람다함수만 사용 할 경우 이름이 없어 임의로 변수에 넣어 사용(실제로 이렇게 사용하진 않음)
2) 여러값을 계산할 때
여러개의 값을 받아 사용할 수 있으며,
여러개를 보낼때는 콤마(,)로 구분하여 사용한다.
multiply = lambda a, b: a * b
print(multiply(3, 4))
# 출력결과 : 12
3) 조건부 표현식과 함께 사용
람다 안에서도 기본적인 조건 표현은 사용할 수 있다.
이는 함수에서 사용하였던 조건부 표현식과 비슷한 형태로
아래의 코드를 예로 들면,
60보다 크거나 같으면 합격, 아니면 불합격를 return한다.
pass_fail = lambda score: "합격" if score >= 60 else "불합격"
print(pass_fail(80)) # 출력결과 : 합격
print(pass_fail(45)) # 출력결과 : 불합격
4) sorted와 함께 사용
sorted() 함수의 경우 key 옵션을 통해
어떤 값을 기준으로 정렬할지 직접 지정할 수 있었다.

기존 방식은 get_score() 함수를 따로 만들어 전달했지만,
간단하게 한 번만 사용할 함수라면
lambda를 사용해서 한 줄로 작성하는 경우가 많다.
또한 reverse=True 옵션을 함께 사용하면
오름차순이 아닌 내림차순 정렬도 가능하다.

코드가 길어질수록 별도 함수가 더 읽기 편할 수도 있지만,
간단한 코드라면 lambda를 사용하면
코드를 짧고 직관적으로 작성할 수 있다.
5) map
리스트의 각 요소에 동일한 변환을 적용할 때 사용할 수 있다.

6) filter
조건을 만족하는 값만 남기는 역할을 한다.
즉, 자료를 조건에 따라 걸러내는 형식이다.

정리
- Scope : 변수가 접근 가능한 범위를 의미한다.
- Local : 함수 내부에서만 사용되고 함수 종료 시 사라진다.
- Global : 전체 코드에서 사용 가능하지만 수정 시 global이 필요하다.
- Enclosing (Closure) : 내부 함수가 외부 함수의 변수를 기억하는 범위다.
- Built-in : Python이 기본으로 제공하는 함수 영역이다.
- Closure : 함수가 종료되어도 변수를 유지하는 구조다.
- Callback : 함수를 다른 함수에 전달해 나중에 실행하는 방식이다.
- Lambda : 이름 없이 간단한 함수를 한 줄로 표현하는 방식이다.
'Python > 기초' 카테고리의 다른 글
| 파이썬 객체지향 프로그래밍(OOP) 4대 패러다임 정리 캡슐화, 상속, 다형성, 다형성, 추상화 쉽게 이해하기 (0) | 2026.06.01 |
|---|---|
| 파이썬 객체지향 프로그래밍 핵심 개념 정리(클래스와 메서드) (0) | 2026.05.28 |
| 파이썬 함수 이해하기 (개념과 동작 방식 정리) (1) | 2026.05.27 |
| 파이썬 반복문 심화 정리(enumerate, zip, iterable, iterator, comprehension) (0) | 2026.05.27 |
| 파이썬 반복문의 기초 정리(While문, for문, range 함수, continue, break, pass) (0) | 2026.05.27 |