내장 함수 활용 가이드
locals: 현재 위치의 모든 지역 변수를 딕셔너리 형태로 반환
globals: 전역 변수를 딕셔너리 형태로 반환
zip: 여러 반복 가능 객체를 결합
sorted: 정렬 기능 제공
filter: 요소 필터링
map: 요소 변환 및 매핑
locals()와 globals() 함수
locals() 함수
locals() 함수는 현재 실행 컨텍스트의 모든 지역 변수를 딕셔너리 형태로 반환합니다.
전역 범위에서 locals()를 사용하는 예시:
value = 100
print(locals()) # 전역 범위에서 실행되므로 전역 변수가 표시됨
# 실행 결과
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000166DC5150D0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:\\Python\\decorator.py', '__cached__': None, 'value': 100}
지역 범위에서 locals()를 사용하는 예시:
global_value = 100
def sample_function():
local_var = 200
print(locals()) # 지역 범위에서 실행되므로 지역 변수만 표시됨
sample_function()
# 실행 결과
{'local_var': 200}
globals() 함수
globals() 함수는 항상 전역 변수를 딕셔너리 형태로 반환하며, 어디에서 호출하든 동일한 결과를 제공합니다.
global_data = 300
def another_function():
local_info = 400
print(globals()) # 지역 함수 내에서 호출되었지만 전역 변수가 표시됨
another_function()
# 실행 결과
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000166DC5150D0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:\\Python\\decorator.py', '__cached__': None, 'global_data': 300, 'another_function': <function another_function at 0x00000166DC7EA020>}
globals() 함수는 호출 위치와 상관없이 항상 전역 범위의 변수를 반환합니다.
zip() 함수
zip() 함수는 여러 반복 가능(iterable) 객체의 요소들을 병합하여 튜플의 시퀀스를 생성합니다.
예를 들어, 여러 리스트의 동일한 인덱스에 있는 요소들을 하나로 묶고 싶을 수 있습니다. 전통적인 방법은 다음과 같습니다:
# 0 1 2
names = ["홍길동", "임꺽정", '이몽룡']
ages = [30, 25, 40]
movies = ["홍길동전", "임꺽정전", "이몽룡전"]
combined = []
for i in range(len(names)):
first_item = names[i]
second_item = ages[i]
third_item = movies[i]
combined.append((first_item, second_item, third_item))
print(combined)
# 실행 결과
[('홍길동', 30, '홍길동전'), ('임꺽정', 25, '임꺽정전'), ('이몽룡', 40, '이몽룡전')]
Python의 zip() 함수를 사용하면 이 작업을 더 간결하게 수행할 수 있습니다:
combined_result = zip(names, ages, movies)
print(dir(combined_result))
# 실행 결과
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__']
dir() 출력 결과에서 __iter__와 __next__ 메서드가 존재함을 알 수 있습니다. 이는 zip()이 반환하는 객체가 반복 가능(iterable)하면서 동시에 반복자(iterator)임을 의미합니다. 따라서 for 루프를 사용하여 모든 요소를 추출할 수 있습니다:
combined_result = zip(names, ages, movies)
for item in combined_result:
print(item)
# 실행 결과
('홍길동', 30, '홍길동전')
('임꺽정', 25, '임꺽정전')
('이몽룡', 40, '이몽룡전')
또한 list() 함수를 사용하여 zip 결과를 바로 리스트로 변환할 수도 있습니다:
combined_result = zip(names, ages, movies)
final_list = list(combined_result)
print(final_list)
# 실행 결과
[('홍길동', 30, '홍길동전'), ('임꺽정', 25, '임꺽정전'), ('이몽룡', 40, '이몽룡전')]
sorted() 함수: 정렬
sorted() 함수의 기본 구문은 다음과 같습니다:
sorted(iterable, key=None, reverse=False)
여기서 매개변수는 다음과 같습니다:
- iterable: 정렬할 반복 가능 객체 (리스트, 튜플 등)
- key: 비교에 사용할 키를 추출하는 함수. 기본값은 None으로, 이 경우 요소 자체를 직접 비교합니다.
- reverse: 정렬 순서를 지정하는 불리언 값. 기본값은 False(오름차순)이며, True로 설정하면 내림차순으로 정렬됩니다.
key와 reverse의 기본값은 None과 False이므로, 반복 가능 객체만 전달하여 기본 정렬을 수행할 수 있습니다:
numbers = [4, 2, 7, 1, 9]
# 기본 오름차순 정렬
sorted_numbers = sorted(numbers)
print(sorted_numbers) # 출력: [1, 2, 4, 7, 9]
key=abs는 절대값을 의미하며, reverse=True는 내림차순, reverse=False는 오름차순입니다:
# 절대값 기준 내림차순 정렬
sorted_by_abs = sorted(numbers, key=abs, reverse=True)
print(sorted_by_abs) # 출력: [9, 7, 4, 2, 1]
주의: sorted() 함수는 새로운 정렬된 리스트를 반환하며 원본 반복 가능 객체를 수정하지 않습니다. 원본을 수정하면서 정렬하려면 리스트의 sort() 메서드를 사용해야 합니다.
key 매개변수의 활용 방법을 고려해봅시다. 다음과 같이 숫자가 아닌 요소가 포함된 리스트를 정렬해야 한다면 어떻게 해야 할까요?
words = ["가을", "김철수", "바다", "강아지", "코끼리"]
이 경우 정렬 함수를 사용하여 key 알고리즘을 처리해야 합니다:
sorted_words = sorted(words, key=len)
print(sorted_words)
하지만 여기서는 람다 함수를 사용하여 더 간결하게 작성할 수 있습니다:
sorted_words = sorted(words, key=lambda x: len(x))
print(sorted_words)
이것이 바로 람다 함수의 주요 용도입니다.
연습 문제:
다음과 같은 딕셔너리 리스트가 있습니다:
employees = [
{"id": 1, "name": "김민준", "age": 28, "salary": 4200},
{"id": 2, "name": "이서준", "age": 32, "salary": 511100},
{"id": 3, "name": "박도윤", "age": 45, "salary": 561230},
{"id": 4, "name": "최지우", "age": 23, "salary": 532100},
{"id": 5, "name": "정하은", "age": 38, "salary": 53210},
{"id": 6, "name": "강지호", "age": 29, "salary": 520},
{"id": 7, "name": "서하준", "age": 51, "salary": 12},
]
- 각 직원의 나이를 기준으로 정렬:
by_age = sorted(employees, key=lambda d: d['age'])
print(by_age)
- 급여를 기준으로 내림차순 정렬:
by_salary = sorted(employees, key=lambda d: d['salary'], reverse=True)
print(by_salary)
filter() 함수: 필터링
filter() 함수는 주어진 함수(불리언 값을 반환하는 함수, 즉 술어 함수)에 따라 시퀀스의 요소를 필터링합니다. 기본 구문은 다음과 같습니다:
filter(function, iterable)
여기서:
- function: 요소를 필터링하는 함수로, True 또는 False를 반환해야 합니다.
- iterable: 필터링할 반복 가능 객체 (리스트, 튜플 등)
filter()는 함수가 True를 반환한 요소들로 구성된 반복자(iterator)를 반환합니다.
다음 리스트에서 성이 "김"인 사람들을 모두 찾아보겠습니다:
names = ["김민준", "이서준", "김지우", "박도윤", "김하준"]
filter()를 사용하여 필터링:
# T F T F T
filtered = filter(lambda x: x.startswith("김"), names)
print(list(filtered))
lambda x: x.startswith("김")은 요소가 "김"으로 시작하는지 확인하는 술어 함수입니다. filter()는 이 함수를 names 리스트의 각 요소에 적용하고, 조건을 만족하는 요소들로 구성된 반복자를 반환합니다. 마지막으로 list()를 사용하여 결과를 리스트로 변환합니다.
"김"씨가 아닌 사람들을 찾으려면 not 연산자를 사용할 수 있습니다:
names = ["김민준", "이서준", "김지우", "박도윤", "김하준"]
not_kim = filter(lambda x: not x.startswith("김"), names)
print(list(not_kim))
주의사항:
- 반환 타입: filter()는 반복자를 반환하므로, 결과를 확인하거나 추가 처리하려면 리스트나 다른 타입으로 변환해야 합니다.
- 술어 함수: 술어 함수는 불리언 값을 반환하며, 요소를 보존할지 여부를 결정합니다.
- 가독성: 복잡한 술어 함수는 코드 가독성을 저하시킬 수 있으므로 신중하게 사용해야 합니다.
map() 함수: 매핑
map() 함수는 반복 가능 객체의 각 요소에 함수를 적용하고, 함수 처리 결과로 구성된 반복자를 반환합니다. 기본 구문은 다음과 같습니다:
map(function, iterable, ...)
여기서:
- function: 각 요소를 처리하는 함수
- iterable: 처리할 반복 가능 객체 (리스트, 튜플 등)
- ...: 여러 반복 가능 객체를 전달할 수 있으며, 이 경우 함수는 해당 수의 매개변수를 받아야 합니다.
map()은 함수를 각 요소에 적용한 결과로 구성된 반복자를 반환합니다.
filter()와 map()의 사용법은 매우 유사하지만, 차이점은 filter()가 요소에 대한 참/거짓 판단을 통해 값을 필터링하고, map()은 요소를 변환하여 변환된 결과를 반환한다는 점입니다.
map()의 활용 분야:
데이터 분석 시 대량의 데이터를 일괄 처리해야 할 경우, 전통적인 리스트 내포 구문으로는 구현이 어려울 수 있으므로 map() 함수가 유용하게 사용될 수 있습니다.
예제:
리스트 내포를 사용하여 모든 숫자의 제곱을 구할 수 있습니다:
numbers = [1,2,3,4,5,6,7,8,9]
squared = [item * item for item in numbers]
print(squared)
# 실행 결과
[1, 4, 9, 16, 25, 36, 49, 64, 81]
map()을 사용하여 동일한 작업을 수행할 수 있습니다:
# 리스트의 모든 요소를 제곱
numbers = [1,2,3,4,5,6,7,8,9]
squared = map(lambda x: x**2, numbers)
print(list(squared)) # 출력: [1, 4, 9, 16, 25, 36, 49, 64, 81]
이 예제에서 lambda x: x**2은 numbers 리스트의 각 요소에 적용되는 함수이며, map()은 각 요소의 제곱으로 구성된 반복자를 반환합니다.
여러 반복 가능 객체 예제:
# 두 리스트의 동일한 위치에 있는 요소들을 더하기
list1 = [1, 2, 3]
list2 = [4, 5, 6]
summed = map(lambda x, y: x + y, list1, list2)
print(list(summed)) # 출력: [5, 7, 9]
이 예제에서 lambda x, y: x + y 함수는 두 개의 매개변수를 받으며, list1과 list2의 동일한 위치에 있는 요소들을 더하여 반환합니다.
주의사항:
- 반환 타입: map()은 반복자를 반환하므로, 결과를 확인하거나 추가 처리하려면 리스트나 다른 타입으로 변환해야 합니다.
- 함수의 매개변수: 함수는 제공된 반복 가능 객체의 수만큼의 매개변수를 받아야 합니다. 여러 반복 가능 객체가 제공된 경우, 함수는 해당 수의 매개변수를 받아야 합니다.
- 가독성: 복잡한 함수는 코드 가독성을 저하시킬 수 있으므로 신중하게 사용해야 합니다.