newhaneul

[Advanced Python Programming] List Comprehension, Lambda, Special Method 본문

4. University Study/Advanced Python Programming

[Advanced Python Programming] List Comprehension, Lambda, Special Method

뉴하늘 2026. 4. 5. 21:33
728x90

포스팅은 인하대학교 허혜선 교수님의 [202601-EEC3408-001] 고급파이썬프로그래밍을 수강하고 공부한 내용을 정리하기 위한 포스팅입니다.

 

 

개념 1. List Comprehension

기존의 반복 가능한 객체를 기반으로 특정한 조건이나 연산을 가해 새로운 리스트를 매우 간결하게 생성하는 파이썬 특유의 문법이다. for 반복문 뒤에 if 조건문을 지정하면 숫자를 생성한 뒤 if 조건문에서 특정 숫자만 뽑아내서 리스트를 생성한다.

 

 리스트 표현식에 for가 여러 개일 때 처리 순서는 뒤에서 앞으로 순으로 처리된다.

 

 

개념 2. Dictionary Comprehension

 List Comprehension과 원리는 거의 같지만, 결과물을 리스트가 아닌 딕셔너리 형태로 반환하는 점이 다르다. 대괄호 대신 중괄호를 사용하며, 내부에서 키와 값을 콜론으로 매핑해 주어야 한다.

words = ['apple', 'banana', 'cherry']

# 단어 자체를 키(key)로, 단어의 길이를 값(value)으로 가지는 딕셔너리 생성
word_lengths = {word: len(word) for word in words}
# 결과: {'apple': 5, 'banana': 6, 'cherry': 6}

 

 

개념 3. map() Function

 map은 리스트, 튜플 등 반복 가능한(iterable) 시퀀스 객체의 모든 요소에 특정 함수를 일괄적으로 적용하는 내장 함수이다. 연산이 완료된 반환값은 메모리 효율을 위해 map 객체 형태로 나오므로, 결과를 확인하거나 리스트로 쓰려면 list() 함수로 감싸주어야 한다.

 

개념 4. Lambda Function

 람다는 def 키워드 대신 사용하여 이름이 없는 익명 함수를 짧게 만드는 방법이다. 코드를 간결하게 작성할 수 있으며, 주로 map이나 filter 같은 다른 함수의 인수로 일회성 함수를 넘겨줄 때 유용하게 쓰인다.

# 일반적인 함수 정의
def add(x, y):
    return x + y

# 람다 함수로 정의
add_lambda = lambda x, y: x + y

 

 

개념 5. Filter() Function

 filter는 반복 가능한 객체의 요소 중에서 특정 조건을 만족하는 요소만 걸러내는 역할을 한다. 즉, 적용된 함수의 반환값이 True인 요소들만 남긴다. 이 역시 반환값이 filter 객체이므로 리스트로 변환해서 사용해야 한다.

numbers = [1, 2, 3, 4, 5, 6]

# 각 요소(x)가 짝수인지(x % 2 == 0) 검사하여 True인 것만 남김
evens = list(filter(lambda x: x % 2 == 0, numbers))
# 결과: [2, 4, 6]

 

 

문제 1. 리스트 컴프리헨션과 딕셔너리 응용 (강의노트 03, 04)

 다음과 같이 학생들의 이름과 점수가 딕셔너리 형태로 들어있는 리스트 students가 주어져 있다.

students = [
    {'name': 'Alice', 'score': 85},
    {'name': 'Bob', 'score': 72},
    {'name': 'Charlie', 'score': 90},
    {'name': 'David', 'score': 65}
]

 

 점수가 80점 이상인 학생의 이름만 대문자로 추출하여 새로운 리스트로 만드는 코드를 리스트 컴프리헨션(List Comprehension)을 사용하여 단 한 줄로 작성해야 한다.

students = [
    {'name': 'Alice', 'score': 85},
    {'name': 'Bob', 'score': 72},
    {'name': 'Charlie', 'score': 90},
    {'name': 'David', 'score': 65}
]

array = [student['name'][0] for student in students if student['score'] >= 80]
print(array)

 

 

 

문제 2. 클래스와 특수 메소드 (강의노트 06, 07)

 2차원 평면의 좌표를 나타내는 Point 클래스를 작성해야 한다. 해당 클래스는 다음 세 가지 조건을 모두 만족해야 한다.

  1. 인스턴스 생성 시 x, y 좌표를 받아 초기화하는 특수 메소드를 작성해야 한다.
  2. 두 Point 객체를 + 연산자로 더하면, 각 좌표끼리 더해진 새로운 Point 객체를 반환하도록 특수 메소드를 작성해야 한다.
  3. print() 함수로 객체 출력 시 (x, y) 형태로 문자열이 반환되도록 특수 메소드를 작성해야 한다.
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

    def __str__(self):
        return f'({self.x}, {self.y})'

a = Point(3, 2)
b = Point(4, 5)

c = a + b
print(c)

 

 

문제 3. 딕셔너리와 가변 키워드 인수 (강의노트 03, 05)

 임의의 개수의 키워드 인수들을 받아, 값이 문자열(str) 자료형인 항목들만 골라낸 뒤 키와 값을 서로 뒤집어서 새로운 딕셔너리를 반환하는 함수 reverse_string_dict(**kwargs)를 작성해야 한다.

# 활용 예시
# reverse_string_dict(a=1, b="apple", c="banana", d=3.14)
# 반환되어야 하는 결과: {"apple": "b", "banana": "c"}
def reverse_string_dict(**kwargs):
    dic = dict()
    for key, value in kwargs.items():
        if type(value) == str:
            dic[value] = str(key)
    return dic

dic = reverse_string_dict(a=1, b="apple", c="banana", d=3.14)
print(dic)

 

 

 

문제 4. 람다(lambda) 함수를 활용한 다중 기준 정렬

 학생들의 이름과 수학, 영어 점수가 딕셔너리 형태로 담긴 리스트 scores가 있다. 이 리스트를 람다(lambda) 함수를 활용하여 수학 점수를 기준으로 먼저 내림차순 정렬하고, 만약 수학 점수가 같다면 영어 점수를 기준으로 오름차순 정렬하는 코드를 한 줄로 작성해야 한다.

scores = [
    {'name': 'Kim', 'math': 80, 'eng': 90},
    {'name': 'Lee', 'math': 95, 'eng': 85},
    {'name': 'Park', 'math': 95, 'eng': 100},
    {'name': 'Choi', 'math': 70, 'eng': 95}
]
# 힌트: sort() 또는 sorted() 함수의 key 매개변수에 lambda를 전달한다.
scores = [
    {'name': 'Kim', 'math': 80, 'eng': 90},
    {'name': 'Lee', 'math': 95, 'eng': 85},
    {'name': 'Park', 'math': 95, 'eng': 100},
    {'name': 'Choi', 'math': 70, 'eng': 95}
]
# 힌트: sort() 또는 sorted() 함수의 key 매개변수에 lambda를 전달한다.

scores.sort(key = lambda student : (-student['math'], student['eng']))

print(scores)
  • key에 tuple을 반환하면, Python은 tuple을 앞에서부터 순서대로 비교하므로 '-student['math']' -> 수학 점수 내림차순, 'student['eng']' -> 영어 점수 오름차순이 적용된다.

 

 

문제 5. 시퀀스 슬라이싱과 딕셔너리 데이터 매핑

 알파벳 문자들이 들어있는 리스트 letters가 주어져 있다. 슬라이싱 기능을 반드시 활용하여 이 리스트의 첫 번째 요소부터 끝까지 두 칸씩 건너뛰며 문자를 추출한다(인덱스 0, 2, 4...). 그 후, 추출된 문자를 키(key)로 하고 문자열 'selected'를 값(value)으로 가지는 딕셔너리 result를 생성하는 코드를 작성해야 한다.

letters = ['a', 'b', 'c', 'd', 'e', 'f']
# 기대 결과: {'a': 'selected', 'c': 'selected', 'e': 'selected'}
# 힌트: 딕셔너리 컴프리헨션이나 반복문과 슬라이싱을 조합하여 작성한다.

result = {k: "selected" for k in letters[::2]}
print(result)

 

 

 

문제 6. map, lambda, 슬라이싱을 결합한 데이터 전처리

 상품 코드가 담긴 리스트 product_codes가 있다. 각 코드는 문자열 형식이며 "국가코드-고유번호-카테고리" 형태를 띠고 있다. 내장 함수 map과 lambda를 활용하여 각 문자열을 슬라이싱해 앞의 세 글자(국가코드와 하이픈 부분)만 잘라내어 새로운 리스트 short_codes를 만드는 코드를 작성해야 한다.

product_codes = ["KOR-101-A", "USA-202-B", "JPN-303-A", "GBR-404-C"]
# 기대 결과: ['KOR', 'USA', 'JPN', 'GBR']
# 힌트: map() 객체는 list() 함수를 통해 리스트로 변환해 주어야 한다.

short_codes = list(map(lambda x : x[:3], product_codes))
print(short_codes)

 

 

 

문제 7. 다중 시퀀스 연산

 두 개의 정수 리스트 list_a와 list_b가 주어진다. map 함수와 lambda 표현식을 사용하여 두 리스트의 같은 인덱스에 위치한 요소들을 각각 제곱한 뒤 서로 더한 값을 가지는 새로운 리스트 result를 생성하는 코드를 단 한 줄로 작성해야 한다.

list_a = [1, 2, 3]
list_b = [4, 5, 6]
# 기대 결과: [17, 29, 45] (예: 1^2 + 4^2 = 17)
# 힌트: map 함수는 여러 개의 시퀀스 객체를 동시에 인수로 받을 수 있다.

result = list(map(lambda x, y : x ** 2 + y ** 2, list_a, list_b))
print(result)

 

 

 

문제 8. 문자열 전처리와 튜플 변환

 쉼표(,)로 구분된 2차원 좌표 문자열들이 담긴 리스트 str_points가 있다. map과 lambda를 활용하여 각 문자열의 쉼표를 기준으로 숫자를 분리하고, 이를 다시 정수형 요소를 가진 튜플(tuple) 형태로 변환하여 새로운 리스트 tuple_points를 만드는 코드를 작성해야 한다.

str_points = ["10,20", "30,40", "50,60"]
# 기대 결과: [(10, 20), (30, 40), (50, 60)]
# 힌트: 문자열의 split() 메서드와 정수형 변환을 적절히 엮어본다.

tuple_points = list(map(lambda x : tuple(map(int, x.split(","))), str_points))
print(tuple_points)

 

 

 

문제 9. 조건부 표현식(삼항 연산자)과의 결합

 학생들의 시험 점수가 담긴 정수 리스트 scores가 있다. map과 lambda 내부에서 파이썬의 조건부 표현식(참일_때_값 if 조건 else 거짓일_때_값)을 사용하여, 점수가 60점 이상이면 'Pass', 60점 미만이면 'Fail' 문자열을 매핑한 새로운 리스트 results를 생성하는 코드를 작성해야 한다.

scores = [45, 80, 59, 90, 100]
# 기대 결과: ['Fail', 'Pass', 'Fail', 'Pass', 'Pass']

results = list(map(lambda x : 'Fail' if x < 60 else 'Pass', scores))
print(results)

 

 

 

문제 10. 리스트 컴프리헨션과 문자열 메서드

 이메일 주소 문자열이 담긴 리스트 emails가 주어진다. 리스트 컴프리헨션을 사용하여, .com으로 끝나는 이메일 주소에서 @ 기호 뒤의 도메인 부분만 대문자로 추출하여 새로운 리스트를 작성해야 한다.

emails = ["user1@gmail.com", "admin@yahoo.com", "test@inha.ac.kr", "hello@daum.net", "info@company.com"]
# 기대 결과: ['GMAIL.COM', 'YAHOO.COM', 'COMPANY.COM']
# 힌트: 문자열의 split() 메서드와 endswith() 메서드를 활용한다.

result = [email.upper().split('@')[1] for email in emails if email[-3:] == 'com']
print(result)

 

 

 

문제 11. map, filter, lambda의 결합

 정수가 담긴 리스트 numbers가 있다. 내장 함수 filter와 map, 그리고 lambda를 함께 사용하여, 주어진 리스트에서 홀수만 골라낸 뒤 그 값을 제곱한 새로운 리스트를 단 한 줄로 작성해야 한다.

numbers = [1, 2, 3, 4, 5, 6, 7]
# 기대 결과: [1, 9, 25, 49]
# 힌트: filter() 결과를 map()의 입력 시퀀스로 전달한다.

result = list(map(lambda x: x ** 2, filter(lambda x : x % 2 != 0, numbers)))
print(result)

 

 

문제 12. 시퀀스 슬라이싱 응용

 문자열 word = "DataScience"가 주어진다. 내장 함수를 사용하지 않고 슬라이싱 문법([start:stop:step])만을 활용하여, 이 문자열을 뒤에서부터 거꾸로 읽되 두 칸씩 건너뛰며 문자를 추출한 새로운 문자열을 만드는 코드를 작성해야 한다.

word = "DataScience"
# 기대 결과: 'eniStD' 

print("".join(list(word[::-2])))

 

 

문제 13. 특수 메소드를 활용한 객체 비교 (__gt__)

 책의 정보를 담는 Book 클래스를 작성해야 한다.

  1. 인스턴스 생성 시 title(제목)과 pages(페이지 수)를 초기화해야 한다.
  2. 두 Book 객체를 > 연산자로 비교했을 때, 왼쪽 객체의 페이지 수가 더 많으면 True를 반환하도록 비교 연산자 특수 메소드(__gt__)를 구현해야 한다.
# 활용 예시
# b1 = Book("Python", 300)
# b2 = Book("Java", 400)
# print(b2 > b1)  # 결과: True

class Book:
    def __init__(self, title, pages):
        self.title = title
        self.pages = pages
    
    def __gt__(self, other):
        return self.pages > other.pages
    
b1 = Book("Python", 300)
b2 = Book("Java", 400)
print(b2 > b1)

 

 

문제 14. 가변 키워드 인수(**kwargs)와 딕셔너리 제어

초기 품목과 수량이 담긴 딕셔너리 inventory와 가변 키워드 인수 **kwargs를 매개변수로 받는 함수 update_inventory(inventory, **kwargs)를 작성해야 한다. 함수는 전달받은 키워드 인수의 값만큼 기존 딕셔너리의 수량에 더하거나 새로운 키를 추가하며, 연산 후 수량이 0 이하가 된 품목은 딕셔너리에서 완전히 삭제한 뒤 해당 딕셔너리를 반환해야 한다.

# 활용 예시
# inv = {'apple': 5, 'banana': 2}
# update_inventory(inv, apple=3, banana=-2, orange=10)
# 기대 결과: {'apple': 8, 'orange': 10} ('banana'는 0이 되어 삭제됨)

def update_inventory(inventory, **kwargs):
    for key, value in kwargs.items():
        if key in inventory:
            inventory[key] += value
        else:
            inventory[key] = value
        
        if inventory[key] <= 0:
        	del inventory[key]
    return inventory

inv = {'apple': 5, 'banana': 2}
print(update_inventory(inv, apple=3, banana=-2, orange=10))

 

 

문제 15. 클로저(Closure) 함수 구현

 호출될 때마다 내부 변수 값이 1씩 증가하여 반환되는 클로저 함수를 생성하는 make_counter() 함수를 작성해야 한다. nonlocal 키워드를 사용하여 외부 함수의 지역 변수를 내부 함수에서 변경할 수 있도록 구현해야 한다.

# 활용 예시
# counter = make_counter()
# print(counter())  # 결과: 1
# print(counter())  # 결과: 2
# print(counter())  # 결과: 3

def make_counter():
    count = 0
    def counter():
        nonlocal count
        count += 1
        return count
    return counter

counter = make_counter()
print(counter())
print(counter())
print(counter())
728x90