python

9. 사용자 정의 함수 ②

cinnamonbrown 2026. 5. 28. 17:35

 

1. 변수의 범위

변수의 범위(scope)는 해당 변수를 프로그램 안에서 어디까지 참조하고 사용할 수 있는지를 의미한다.

파이썬에서는 변수가 선언된 위치에 따라 사용할 수 있는 범위가 달라진다.


1.1 지역 변수

  • 가장 내부의 범위로 함수 내에서 정의된 변수들이 지역 변수에 해당된다.
  • 함수 안에서 만들어진 변수는 그 함수 안에서만 사용할 수 있다.

예시

 

👉 위 코드에서 local_varlocal_example() 함수 안에서 만들어진 변수이다.

 

따라서 함수 안에서는 정상적으로 사용할 수 있지만, 함수 밖에서 local_var를 사용하려고 하면 오류가 발생한다.


1.2 전역(글로벌) 변수

  • 스크립트 전체에서 사용되는 범위로, 함수외부에서 정의된 변수가 해당된다
  • 모든 함수에서 접근할 수 있지만, 함수 내부에서 수정하려면 global키워드가 필요하다

예시 1

 

👉 global_var 은 전역변수이다.

 

👉그래서 test_global_scope() 함수 안에서도 접근할 수 있고, 함수 밖에서도 그대로 사용할 수 있다.


 

예시 2 – 전역변수와 지역 변수의 이름이 같을 때

 

👉 global_var=10 ⇨전역변수

 

👉 modify_global() 함수 안의 global_var=20 ⇨ 전역 변수의 값을 바꾼 것이 아니다.
함수 안에서 같은 이름의 지역 변수를 새로 만든 것이다


👉 그래서 함수 안에서는 20이 출력되고, 함수 밖에서는 원래 전역 변수 값인 10이 그대로 출력된다.


 

예시 3 – global 키워드

만약 함수 안에서 전역 변수의 값을 직접 수정하고 싶다면 global 키워드를 사용해야 한다.

 

 

👉 global global_var라고 작성하면, 함수 안에서 사용하는global_var가 지역 변수가 아니라 전역 변수라는 뜻이 된다.

👉 그래서 함수 안에서 global_var = 20을 실행하면 실제 전역 변수의 값이 바뀐다.

 


✔️ 함수 안에 함수가 들어 있는 구조

파이썬에서는 함수 안에 또 다른 함수를 정의할 수 있다.

 

 

👉 여기서 outer_function() 안에 inner_function()이 들어 있다.

 

👉 그리고 inner_function()은 바깥 함수인 outer_function()의 변수 enclosing_var를 사용하고 있다.

 

👉 위 코드를 실행하면 outer_function()은 내부 함수인 inner_function 자체를 반환한다.

 

👉 그래서 f에는 inner_function이 저장되고, f()를 실행하면 내부 함수가 실행된다.

 

👉 이때 outer_function()의 실행은 이미 끝났는데도, inner_function()이 여전히 enclosing_var를 기억하고 있다.


클로저 공간

클로저 공간은 `내부 함수가 외부 함수의 변수를 계속 사용할 수 있도록, 그 값을 따로 저장해두는 메모리 영역(객체 구조)이다.

일반적으로 함수가 끝나면 그 안의 지역 변수는 사라진다.

하지만, 내부 함수가 그 변수를 참조하고 있으면 파이썬은 해당 값을 지우지 않고 함수 객체 안에 __closure__라는 형태로 보관한다.

이때 저장되는 값은 보통 cell 객체로 감싸져 유지되며, 내부 함수는 실행될 때 이 클로저 공간을 통해 외부 변수에 접근할 수 있다.


🔸 빌트인 함수

  • 파이썬에서 별도의 import 없이 바로 사용할 수 있도록 기본적으로 제공되는 함수
  • ex) print(), len(), type(), range()
  • 파이썬이 실행될 때 자동으로 Built-in 네임스페이스에 등록되어 있기 때문에 이름만으로 호출할 수 있다

✅ 빌트인 함수 이름을 함부로 변수로 사용하면 안되는 이유

파이썬에서는 빌트인 함수 이름도 변수 이름처럼 사용할 수 있다.
하지만 그렇게 하면 원래 함수가 가려질 수 있다.

len = 5  # 내장 함수 'len'을 덮어씀
#print(len([1, 2, 3]))  # 오류 발생! 

 

👉 위 코드에서 len이라는 이름에 숫자 5를 넣어버렸기 때문에, 파이썬은 더 이상 len을 함수로 보지 않는다.

 

 

그래서 len([1, 2, 3])처럼 사용하면 오류가 발생한다.

또한, str 같은 이름도 가능하면 변수명으로 사용하지 않는 것이 좋다.


✅ LEGB 규칙

빌트인 함수는 변수 이름을 찾을 때 적용되는 LEGB 규칙의 마지막 단계에 해당한다.

LEGB 규칙이란 파이썬에서 변수를 찾을 때 정해진 순서대로 이름을 검색하는 규칙이다.

즉, 파이썬은 이름을 찾을 때 가까운 범위부터 순서대로 탐색한다고 이해할 수 있다.

Local(지역변수) 
→ Enclosing(둘러싸인, 함수 안의 함수) 
→ Global(전역 변수) 
→ Built-in(빌트인 함수)

따라서 위의 예시처럼 같은 이름의 변수를 직접 정의하면 기존 빌트인 함수가 가려질 수 있다는 것이다.

 


4. 함수 메모리 제거

함수도 파이썬 객체이므로 참조 카운팅가비지 컬렉션의 원칙에 따라 동작한다.

함수를 참조하는 이름(변수)이 더 이상 없으면, 해당 함수 객체는 가비지 컬렉션 대상이 될 수 있다.

del 명령어를 사용하여 함수에 대한 참조를 명시적으로 제거할 수 있지만 이것이 곧 함수가 즉시 메모리에서 제거된다는 것을 보장하지는 않는다.

def func1():
    print('처음으로 만드는 함수')


del func1
# 이후 func1()을 호출하려고 하면 오류가 발생함
func1()

실행 결과


5. 콜백 함수 (⭐️⭐️⭐️⭐️⭐️)

콜백 함수(callback function)

다른 함수에 인자로 전달되어, 특정 시점이나 조건이 되었을 때 나중에 호출되는 함수를 의미한다.

파이썬에서는 함수도 객체이기 때문에 변수처럼 전달할 수 있다.

따라서, 이를 활용해 특정 시점에 실행할 동작을 미리 정의해둘 수 있다.

즉, 콜백 함수는 “지금 바로 실행하는 함수”가 아니라, 다른 함수에게 맡겨두었다가 필요할 때 호출되도록 하는 함수이다.


 

예시 1

👉

execute(say_hello)

 

이 코드는 say_hello()를 실행하는 것이 아니다. 함수 자체를 전달한 것이다.


예시 2

def print_score(score):
  print(f'score : {score}')


def print_pass_fail(score):
  if score >= 80:
        print(f"{score}점: 합격")
  else:
      print(f"{score}점: 불합격")

def process_scores(scores,callback):
    for score in scores:
        callback(score)


def print_bonus_score(score):
    print(f"보너스 적용 점수 : {score + 5}")

scores = [80, 95, 70, 100, 60]

print("원점수 출력")

process_scores(scores,print_score)

print("합격,불합격 출력")
process_scores(scores,print_pass_fail)

print("==보너스 점수 출력==")
process_scores(scores,print_bonus_score)

실행 결과

👉

process_scores(scores,print_score)
process_scores(scores,print_pass_fail)
process_scores(scores,print_bonus_score)

 

여기서 process_scores에 순서대로 print_scoreprint_pass_fail -> print_bonus_score 함수들을 인자로 전달한 것이다.


예시 3

콜백 함수 개념은 sorted()에서도 자주 등장한다.
예를 들어 dict으로 저장된 학생 정보 관련 리스트를 점수 기준으로 정렬한다고 해보자.

students = [
    {"name": "김사과", "score": 90},
    {"name": "반하나", "score": 75},
    {"name": "오렌지", "score": 100}
]

def get_score(student): # 학생 한 명 한명이 들어가면 score 을 뽑는다
  return student["score"]
result= sorted(students, key=get_score) 

실행 결과

[{'name': '반하나', 'score': 75}, {'name': '김사과', 'score': 90}, {'name': '오렌지', 'score': 100}]

 

 

👉 여기서

key=get_score

 

부분을 잘 살펴보자

 

👉 sorted()는 학생 한 명씩 꺼내서
get_score(student) 를 호출하고, 반환된 값을 기준으로 정렬한다.

 

즉,

90 → 75 → 100 이라는 점수를 꺼내 비교해서

75 → 90 → 100
순서로 정렬하는 것이다.

 

👉 데이터 분석처럼 다뤄야 할 항목들이 많을 때 이런 방식의 정렬을 자주 사용한다.


6. 람다 함수

람다 함수(lambda function)는 파이썬에서

이름 없이 간단한 함수를 한 줄로 정의할 수 있는 익명 함수로,

주로 짧고 일회성으로 사용되는 연산을 표현할 때 활용된다.

일반 함수(def)에 비해 구조는 제한적이지만 코드가 간결해지고,

특히 sorted, map, filter 같은 함수에서 콜백 함수로 자주 사용된다.


 

예시 1

이걸 람다 함수로 바꾸면 다음과 같이 작성할 수 있다.

 

 

✅ 람다 함수 문법은 다음과 같다.

lambda 매개변수: 반환값

즉,

  • : 왼쪽 → 매개변수
  • : 오른쪽 → return 될 값

이라고 생각하면 된다.


예시 2 – 조건문이 들어간 람다 함수

람다 함수 안에서도 간단한 조건문을 사용할 수 있다.

 

👉 이 람다 함수에는 조건부 표현식이 이용되었다

조건부 표현식은

"참일 때 값" if 조건 else "거짓일 때 값"

구조이다.

즉,

score >= 60

이면 "합격"을 반환하고,

그렇지 않으면 "불합격"을 반환하는 구조이다.


예시 3 – sorted()와 람다함수

람다 함수는 정렬할 때 정말 자주 등장한다.

 

 

예를 들어 학생 정보를 점수 기준으로 내림차순 정렬한다고 해보자.

students = [
    {"name": "김사과", "score": 90},
    {"name": "반하나", "score": 75},
    {"name": "오렌지", "score": 100},
]

# result= sorted(students, key=get_score) 

result= sorted(students,key=lambda student : student["score"], reverse=True)

print(result)

 

 

👉 여기서 아래 부분이 처음에 헷갈렸다.

key=lambda student : student["score"]

파이썬은 students 안의 데이터를 하나씩 꺼내면서

student["score"]

를 실행한다.

즉,

90 → 75 → 100

이라는 점수를 꺼내고,

그 값을 기준으로 학생 정보를 정렬하는 것이다.

👉 reverse=True는 내림차순 정렬을 의미하기 때문에 students는 큰 점수를 받은 학생 순으로 정렬된다.


 

예시 4 – map()과 람다 함수

map() 함수는 리스트의 각 요소에 같은 작업을 반복 적용할 때 사용한다.

문법은 다음과 같다.

map(함수, 반복가능한 객체)

즉, 리스트 전체에 같은 함수를 반복 적용한다고 생각하면 이해하기 쉽다.
예를 들어 모든 점수에 10점을 더한다고 해보자.

여기서

lambda score: score + 10

은 점수를 하나씩 받아서 10을 더하는 함수이다.

 

 

👉 list()를 씌운 이유는 map()이 결과를 바로 리스트로 반환하지 않기 때문이다.

 

map 객체 형태로 반환되기 때문에, 실제 값을 보기 위해 list()로 변환해주었다.


예시 5 – filter()와 람다 함수

filter()는 조건에 맞는 데이터만 걸러낼 때 사용한다.

문법은 다음과 같다.

filter(함수, 반복가능한 객체)

예를 들어 60점 이상인 점수만 남긴다고 해보자.

 

 

👉 파이썬은 리스트를 하나씩 확인하면서

score >= 60

조건을 검사한다.

 

 

조건이 True인 값만 남기기 때문에,

70, 88, 100

만 결과로 남는다.

 

 

👉 filter() 역시 filter 객체를 반환하기 때문에 실제 값을 확인하려면 list()로 감싸서 사용한다.

'python' 카테고리의 다른 글

11. 객체 지향 프로그래밍 4대 패러다임 ①  (0) 2026.05.28
10. 객체지향 프로그래밍  (0) 2026.05.28
9. 사용자 정의 함수 ①  (0) 2026.05.27
Python - 제어문-반복문  (0) 2026.05.27
Python - 컬렉션 - 튜플(tuple)  (0) 2026.05.26