IT/μ»΄ν“¨νŒ…μ  사고

Python μ»΄ν”„λ¦¬ν—¨μ…˜ 및 ν‘œν˜„μ‹ 정리

Unused 2025. 3. 27. 17:14

Credit: https://www.linkedin.com/pulse/python-tips-list-comprehensions-hugo-tota

Python으둜 μ•Œκ³ λ¦¬μ¦˜μ„ 곡뢀할 λ•Œ 놓칠 수 μ—†λŠ” κ°œλ…λ“€ 쀑 ν•˜λ‚˜κ°€ λ°”λ‘œ μ»΄ν”„λ¦¬ν—¨μ…˜(comprehension)κ³Ό ν‘œν˜„μ‹(expression)μž…λ‹ˆλ‹€. Pythonμ—μ„œλŠ” 반볡문과 쑰건문을 κ°„κ²°ν•˜κ²Œ ν‘œν˜„ν•  수 μžˆλŠ” list comprehension, generator expression, conditional expression(μ‚Όν•­ μ—°μ‚°μž) 등을 μ œκ³΅ν•˜μ—¬, μ μ ˆν•˜κ²Œ μ‚¬μš© μ‹œ μ„±λŠ₯(싀행속도)κ³Ό 간결함을 λ‘˜ λ‹€ μž‘μ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

이번 ν¬μŠ€νŠΈμ—μ„œλŠ” 각쒅 μ»΄ν”„λ¦¬ν—¨μ…˜ 및 ν‘œν˜„μ‹μ˜ κ°œλ…κ³Ό μ‚¬μš©λ²•μ„ μ •λ¦¬ν•©λ‹ˆλ‹€.

μ•„μšΈλŸ¬, 이듀에 λžŒλ‹€(lambda)μ‹κΉŒμ§€ μ μš©ν•œ μ˜ˆμ œλ„ ν•œλ²ˆ μ‚΄νŽ΄λ³΄μ‹œκ² μŠ΅λ‹ˆλ‹€.


λͺ©μ°¨:

1. List Comprehensions
2. Set Comprehensions
3. Dictionary Comprehensions
4. Generator Expressions
5. Conditional Expressions
6. Nested Loops in Comprehensions/Expressions
7. Lambda μ μš©ν•˜κΈ°
8. 더 λ‚˜μ•„κ°€κΈ° - μ•ˆν‹°νŒ¨ν„΄


1. List Comprehensions

리슀트 μ»΄ν”„λ¦¬ν—¨μ…˜(List Comprehension)은 κΈ°μ‘΄ λ¦¬μŠ€νŠΈλ‚˜ μ΄ν„°λŸ¬λΈ” 객체(λ°˜λ³΅κ°€λŠ₯ 객체)μ—μ„œ μƒˆλ‘œμš΄ 리슀트λ₯Ό κ°„κ²°ν•˜κ³  효율적으둜 생성할 수 있게 ν•΄μ£ΌλŠ” λ¬Έλ²•μž…λ‹ˆλ‹€. forλ¬Έ 뒀에 ifλ₯Ό λΆ™μž„μœΌλ‘œμ¨ 필터링 κΈ°λŠ₯도 μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

[ν‘œν˜„μ‹ for λ³€μˆ˜ in μ΄ν„°λŸ¬λΈ” if 쑰건]

νŠΉμ§•:

  • 필터링과 λ³€ν™˜μ„ λ™μ‹œμ— 처리
  • κΈ°μ‘΄ for문보닀 λΉ λ₯΄κ³ , μ½”λ“œλ„ 짧음 ==> μ„±λŠ₯ & 가독성 κ°œμ„ 
  • 쑰건뢀 ν‘œν˜„μ‹ (conditional expressions)와 ν•¨κ»˜ μ‚¬μš© κ°€λŠ₯ ==> 필터링 κΈ°λŠ₯

예제 1-0: range()둜 0λΆ€ν„° 9κΉŒμ§€μ˜ 리슀트 생성

# 기쑴 for문
numbers_list = []
for x in range(10):
    numbers_list.append(x)

# List comprehension 적용
numbers_list = [x for x in range(10)]

# 좜λ ₯
print(numbers_list) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

예제 1-1: λ¬Έμžμ—΄ ν˜•νƒœμ˜ μž…λ ₯을 μ •μˆ˜ν˜•μœΌλ‘œ λ³€ν™˜ => 리슀트둜 생성

numbers_str = "1 2 43 2 325 25 5 354 36 47"
numbers_list = [x for x in map(int, numbers_str.split())]

# 좜λ ₯
print(numbers_list)  # [1, 2, 43, 2, 325, 25, 5, 354, 36, 47]

예제 1-2: 단어 길이 κ΅¬ν•˜κΈ°

sentence = "Python is fun"
word_lengths = [len(word) for word in sentence.split()]
print(word_lengths)  # [6, 2, 3]

예제 1-3: 1λΆ€ν„° 10κΉŒμ§€ 쀑 짝수만 필터링 ν›„ 각각의 제곱수 좜λ ₯

squares = [x**2 for x in range(1, 11) if x % 2 == 0]
print(squares)  # [4, 16, 36, 64, 100]

예제 1-4: (μš”μ†Œ, 제곱)의 νŠœν”Œμ˜ 리슀트 생성

numbers = [1, 2, 3, 4]
tuple_list = [(x, x**2) for x in numbers]
print(tuple_list)  # [(1, 1), (2, 4), (3, 9), (4, 16)]

예제 1-5: 2차원 리슀트 생성 (μ€‘μ²©λœ 리슀트 μ»΄ν”„λ¦¬ν—¨μ…˜)

# 3개의 ν–‰(row)와 2개의 μ—΄(column)을 κ°€μ§€λŠ” 2차원 리슀트
# 즉 2x3의 2차원 리슀트 - ν—·κ°ˆλ¦¬μ‹ λ‹€λ©΄, 천천히 λ³΄μ„Έμš”, 6. Nest Loops ν•­λͺ©μ—μ„œ 더 ν—·κ°ˆλ¦¬μ‹€ 수 μžˆμŠ΅λ‹ˆλ‹€

matrix_a = [[None]*2 for i in range(3)]
matrix_b = [[None for j in range(2)] for i in range(3)]

print(matrix_a) # [[None, None], [None, None], [None, None]]
print(matrix_b) # [[None, None], [None, None], [None, None]]

예제 1-6: ꡬꡬ단 2차원 리슀트 생성 (μ€‘μ²©λœ 리슀트 μ»΄ν”„λ¦¬ν—¨μ…˜)

multiplication_table = [[i * j for j in range(1, 10)] for i in range(2, 10)]
print(row)

 

2. Set Comprehensions

μ§‘ν•©(set)을 μƒμ„±ν•˜λŠ” μ»΄ν”„λ¦¬ν—¨μ…˜. 리슀트 μ»΄ν”„λ¦¬ν—¨μ…˜κ³Ό κ°™μ§€λ§Œ μ€‘κ΄„ν˜Έ {}둜 감싸고, 쀑볡 없이 μš”μ†Œλ₯Ό μˆ˜μ§‘ν•©λ‹ˆλ‹€.

{ν‘œν˜„μ‹ for λ³€μˆ˜ in μ΄ν„°λŸ¬λΈ” if 쑰건}

νŠΉμ§•:

  • 쀑볡 제거된 κ²°κ³Όκ°€ μžλ™ 생성됨
  • 데이터 필터링 ν›„ 쀑볡 μ—†λŠ” κ²°κ³Ό ν•„μš”ν•  λ•Œ 유용

예제 2-1: λ¬Έμžμ—΄μ—μ„œ λͺ¨μŒ μΆ”μΆœν•˜μ—¬ μ§‘ν•© 생성

text = "Hello World"
vowels = {char.lower() for char in text if char.lower() in 'aeiou'}
print(vowels)  # {'e', 'o'}

예제 2-2: 1λΆ€ν„° 21κΉŒμ§€, 5의 배수의 μ§‘ν•© 생성

multiples_of_5 = {x for x in range(1, 21) if x % 5 == 0}
print(multiples_of_5)  # {5, 10, 15, 20}

 

3. Generator Expressions

μ œλ„ˆλ ˆμ΄ν„° ν‘œν˜„μ‹μ€ 리슀트 μ»΄ν”„λ¦¬ν—¨μ…˜κ³Ό μœ μ‚¬ν•˜μ§€λ§Œ ()둜 κ°μŒ‰λ‹ˆλ‹€. 값을 ν•˜λ‚˜μ”© μƒμ„±ν•˜λ―€λ‘œ (lazy evaluation), 이λ₯Ό 잘 ν™œμš©ν•˜λ©΄ λ©”λͺ¨λ¦¬λ₯Ό 덜 μ“Έ 수 μžˆμŠ΅λ‹ˆλ‹€.

(ν‘œν˜„μ‹ for λ³€μˆ˜ in μ΄ν„°λŸ¬λΈ” if 쑰건)

νŠΉμ§•:

  • λ©”λͺ¨λ¦¬μ— λͺ¨λ“  μš”μ†Œλ₯Ό μ˜¬λ¦¬μ§€ μ•Šκ³ , ν•˜λ‚˜μ”© lazy evaluation
  • sum(), max(), any(), all()κ³Ό ν•¨κ»˜ 자주 μ‚¬μš©ν•©λ‹ˆλ‹€.
  • 값을 단 ν•œ 번만 κΊΌλ‚Ό 수 μžˆμŠ΅λ‹ˆλ‹€. 즉 μž¬μ‚¬μš© λΆˆκ°€

예제 3-1: 1λΆ€ν„° 11κΉŒμ§€μ˜ μ œκ³±μ„ ν”„λ¦°νŠΈ

squares_gen = (x**2 for x in range(1, 11))
for square in squares_gen:
    print(square)

예제 3-2: 3의 배수의 ν•© (μ œλ„ˆλ ˆμ΄ν„° ν‘œν˜„μ‹)

sum_of_multiples = sum(x for x in range(1, 101) if x % 3 == 0)
print(sum_of_multiples)  # 1683

예제 3-3: 2차원 λ¦¬μŠ€νŠΈμ—μ„œ 쑰건 만쑱 μš”μ†Œ 개수 μ„ΈκΈ°

matrix = [
    [3, 5, 7],
    [2, 6, 4],
    [8, 1, 9]
]
count_ge_5 = sum(1 for row in matrix for item in row if item >= 5)
print(count_ge_5)  # 5

예제 3-4: 리슀트 ν•©κ³Ό 평균 κ³„μ‚°ν•˜κΈ°

numbers = [10, 20, 30, 40, 50]
total = sum(x for x in numbers)
average = total / len(numbers)
print(total, average)  # 150 30.0

 

4. Conditional Expressions

μ»΄ν”„λ¦¬ν—¨μ…˜ λ‚΄λΆ€μ—μ„œ μ‚¬μš©ν•  수 μžˆλŠ” μ‚Όν•­ μ—°μ‚°μžμž…λ‹ˆλ‹€. λ‚˜μ˜€λŠ” κ°’ 자체λ₯Ό 쑰건에 따라 λ°”κΏ€ λ•Œ μ‚¬μš©λ©λ‹ˆλ‹€. 예제 1-3.μ—μ„œ λ³΄μ—¬λ“œλ¦° ν•„ν„°λ§κ³ΌλŠ” κ΅¬λ³„λ˜λŠ” κ°œλ…μž…λ‹ˆλ‹€. for문을 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” ν‘œν˜„μ‹λ„ μ‘΄μž¬ν•©λ‹ˆλ‹€ (예제 4-1).

[μ°ΈμΌλ•Œμ˜κ°’ if 쑰건 else κ±°μ§“μΌλ•Œμ˜κ°’ for λ³€μˆ˜ in μ΄ν„°λŸ¬λΈ”]

νŠΉμ§•:

  • λ‚˜μ˜€λŠ” κ°’ 자체λ₯Ό 쑰건에 따라 λ³€ν™˜ν•¨ ==> ν•„ν„°λ§κ³ΌλŠ” 닀름!
  • 필터링과 ν˜Όλ™ν•˜μ§€ μ•Šλ„λ‘ 주의

예제 4-1: κ²½μš°μ— λ”°λ₯Έ λ¬Έμžμ—΄ 좜λ ₯

def foo():
    return True

foo_result = 'YES' if foo() else 'NO'

print(foo_result) # YES

예제 4-2: 쑰건뢀 ν‘œν˜„μ‹μ„ μ‚¬μš©ν•œ 리슀트 λ³€ν™˜

numbers = [1, 2, 3, 4, 5, 6]
even_or_zero = [x if x % 2 == 0 else 0 for x in numbers]
print(even_or_zero)  # [0, 2, 0, 4, 0, 6]

예제 4-3: 짝수/ν™€μˆ˜ λ§€ν•‘ 리슀트 μƒμ„±ν•˜κΈ°

numbers = [1, 2, 3, 4, 5]
parity = ["Even" if x % 2 == 0 else "Odd" for x in numbers]
print(parity)  # ['Odd', 'Even', 'Odd', 'Even', 'Odd']

 

5. Dictionary Comprehensions

λ”•μ…”λ„ˆλ¦¬ μ»΄ν”„λ¦¬ν—¨μ…˜μ€ {key: value} ν˜•νƒœλ‘œ λ”•μ…”λ„ˆλ¦¬λ₯Ό λΉ λ₯΄κ²Œ μƒμ„±ν•©λ‹ˆλ‹€. Set처럼 { }λ₯Ό μ‚¬μš©ν•˜μ§€λ§Œ, μ–˜λŠ” key: value의 μ‘°ν•©μ΄λ―€λ‘œ, :κ°€ λ“€μ–΄κ°μœΌλ‘œμ¨ set comprehensions와 κ΅¬λ³„λ©λ‹ˆλ‹€.

{key_expr: value_expr for λ³€μˆ˜ in μ΄ν„°λŸ¬λΈ” if 쑰건}

νŠΉμ§•:

  • ν‚€-κ°’ μŒμ„ λ™μ μœΌλ‘œ 생성할 λ•Œ 유용
  • νŠΉμ • κ·œμΉ™μœΌλ‘œ λ§€ν•‘λœ λ”•μ…”λ„ˆλ¦¬λ₯Ό λ§Œλ“€κΈ° μ’‹μŒ

예제 5-1: μˆ«μžμ™€ 제곱의 λ”•μ…”λ„ˆλ¦¬ λ§Œλ“€κΈ°

numbers = [1, 2, 3, 4, 5]
square_dict = {x: x**2 for x in numbers}
print(square_dict)  # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

예제 5-2: λ¬Έμžμ—΄μ˜ 첫 κΈ€μžμ— λ”°λ₯Έ μ•ŒνŒŒλ²³ μˆœμ„œ 번호 λ”•μ…”λ„ˆλ¦¬

words = ['apple', 'banana', 'cherry']
alpha_index = {word: ord(word[0].lower()) - ord('a') + 1 for word in words}
print(alpha_index)  # {'apple': 1, 'banana': 2, 'cherry': 3}

예제 5-3: κ·Έλž˜ν”„μ—μ„œ, 각 λ…Έλ“œλ₯Ό λ”•μ…”λ„ˆλ¦¬λ‘œ μ €μž₯ (λ°±μ€€ 1991 "트리 순회" μ°Έμ‘°)

이 μ˜ˆμ œλŠ” generator expressionκ³Ό dictionary comprehension을 μ€‘μ²©ν•œ κ²½μš°μž…λ‹ˆλ‹€.

# μž…λ ₯ μ˜ˆμ‹œ - λ°±μ€€ 1991 "트리 순회" μ°Έμ‘°
"""
A B C
B D .
C E F
E . .
F . G
D . .
G . .
"""
tree = {root: (left, right) for root, left, right in (input().split() for _ in range(n))}
print(tree) # {'A': ('B', 'C'), 'B': ('D', '.'), 'C': ('E', 'F'), 'E': ('.', '.'), 'F': ('.', 'G'), 'D': ('.', '.'), 'G': ('.', '.')}


6. Nested Loops in Comprehensions/Expressions

Nested loops, 즉, 2개 μ΄μƒμ˜ for문이 μ€‘μ²©λ˜λŠ” ν˜•νƒœμž…λ‹ˆλ‹€. 닀차원 리슀트 등을 λ§Œλ“€κ±°λ‚˜ μ—¬λŸ¬ 리슀트의 쑰합을 계산할 λ•Œ μœ μš©ν•©λ‹ˆλ‹€. Nested comprehensions/expressionsμ™€λŠ” κ΅¬λ³„λ˜λŠ” κ°œλ…μž…λ‹ˆλ‹€.

[ν‘œν˜„μ‹ for λ³€μˆ˜1 in μ΄ν„°λŸ¬λΈ”1 for λ³€μˆ˜2 in μ΄ν„°λŸ¬λΈ”2 ...]

νŠΉμ§•:

  • 이쀑 λ°˜λ³΅λ¬Έμ„ ν•œ μ€„λ‘œ ν‘œν˜„ κ°€λŠ₯
  • 닀차원 ꡬ쑰(ν–‰λ ¬ λ“±)에 적합

예제 6-1: 리슀트 μ‘°ν•©μœΌλ‘œ νŠœν”Œ 생성

pairs = [(x, y) for x in [1, 2, 3] for y in ['a', 'b']]
print(pairs) # [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b'), (3, 'a'), (3, 'b')]

예제 6-2: 리슀트 μ‘°ν•©μœΌλ‘œ 각 ν•©μ˜ 리슀트 생성

list1 = [1, 2]
list2 = [10, 20, 30]
combination_sums = [x + y for x in list1 for y in list2]
print(combination_sums)  # [11, 21, 31, 12, 22, 32]

예제 6-3: 닀차원 리슀트λ₯Ό λ‹¨μ°¨μ›μœΌλ‘œ 펴기 (flattening)

my_lists = [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]
flat = [fooooooo for sublist1 in my_lists for sublist2 in sublist1 for fooooooo in sublist2]
print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

예제 6-4: 닀차원 리슀트 내에 0μ΄λΌλŠ” 값이 μ‘΄μž¬ν•˜λ©΄ "YES", μ—†μœΌλ©΄ "NO" ν‘œμ‹œ

# 리슀트 내에 0μ΄λΌλŠ” 값이 ν•˜λ‚˜λΌλ„ μ‘΄μž¬ν•˜λ©΄ "YES", μ΄μ™Έμ—λŠ” "NO"λ₯Ό ν”„λ¦°νŠΈ
block = [[[0, -1, 0, 0, 0], [-1, -1, 0, 1, 1], [0, 0, 0, 1, 1]]]
print("YES" if any(0 in col for row in block for col in row) else "NO") # YES
더보기
# μ λ‹Ήν•œ indentation 적용 μ‹œ
print("YES" if any( 0 in col 
                    for row in block 
                    for col in row)  else "NO")

β€» μœ„ 1. List Comprehensions의 2차원 리슀트 생성과 λΉ„κ΅ν•˜μ—¬, for문을 μ–΄λ–€ μˆœμ„œλ‘œ 읽어야 ν• μ§€λ₯Ό μ€‘μ μ μœΌλ‘œ λ³΄μ„Έμš”.

 

7. Lambda μ μš©ν•˜κΈ°

Lambdaλž€ μ‰½κ²Œ λ§ν•˜λ©΄ '읡λͺ… ν•¨μˆ˜'둜, 단일 λ¬Έμž₯(1쀄)의 μ½”λ“œλ‘œ μž‘μ„±λ©λ‹ˆλ‹€. ν•¨μˆ˜ λ‚΄λΆ€μ—λŠ” return문이 ν¬ν•¨λ˜μ§€ μ•Šμ§€λ§Œ, 식 μžμ²΄λ‘œλΆ€ν„° λ‚˜μ˜€λŠ” 값을 λ°˜ν™˜ν•©λ‹ˆλ‹€.

μœ„ comprehensions 및 expressions에 lambdaλ₯Ό μ μš©ν•˜μ—¬, 기쑴의 μ΄ν„°λŸ¬λΈ” κ°μ²΄λ‘œλΆ€ν„° μƒˆλ‘œμš΄ 리슀트 등을 κ°„κ²°ν•˜κ²Œ 생성할 수 μžˆμŠ΅λ‹ˆλ‹€.

# μ•„λž˜λŠ” x+y 값을 λ°˜ν™˜ν•˜λŠ” lambdaμ‹μž…λ‹ˆλ‹€.
add = lambda x, y: x + y

예제 7-1: 각 μš”μ†Œμ˜ 제곱의 리슀트 μ»΄ν”„λ¦¬ν—¨μ…˜ ==> ν”„λ¦°νŠΈ

numbers = [1, 2, 3, 4, 5]
square = lambda x: x ** 2
squares = [square(x) for x in numbers]
print(squares)  # [1, 4, 9, 16, 25]

예제 7-2: 짝수인 μš”μ†Œλ§Œ μΆ”λ €μ„œ ν•΄λ‹Ή μš”μ†Œλ“€μ˜ 제곱의 μ œλ„ˆλ ˆμ΄ν„° ν‘œν˜„μ‹ => 합계 

square = lambda x: x ** 2
sum_of_even_squares = sum(square(x) for x in range(1, 11) if x % 2 == 0)
print(sum_of_even_squares)  # 220 (4 + 16 + 36 + 64 + 100)

 

8. 더 λ‚˜μ•„κ°€κΈ° - μ•ˆν‹°νŒ¨ν„΄

μ„œλ‘μ— μ„±λŠ₯와 간결함을 μž‘μ„ 수 μžˆλ‹€κ³  μ–ΈκΈ‰ λ“œλ ΈμœΌλ‚˜, 식이 μ§€λ‚˜μΉ˜κ²Œ λ³΅μž‘ν•΄μ§€λŠ” κ²½μš°μ—λŠ” 였히렀 일반적인 λ°˜λ³΅λ¬Έλ³΄λ‹€ 가독성이 λ‚˜λΉ μ§€κ²Œ λ©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, μ•„λž˜μ™€ 같이 μ§œλŠλ‹ˆ 차라리 기쑴의 λ°©μ‹λŒ€λ‘œ μž‘μ„±ν•˜λŠ” 것이 쒋을 수 μžˆμŠ΅λ‹ˆλ‹€.

# κ²½κ³ : μ•„λž˜ μ½”λ“œλŠ” 고의둜 λ‚œν•΄ν•˜κ²Œ, μœ μ§€λ³΄μˆ˜ν•˜κΈ° νž˜λ“€λ„λ‘ μž‘μ„±ν•œ μ•ˆν‹°νŒ¨ν„΄ μ˜ˆμ‹œμž„.
bad_sample = {f"key_{i}": ([[[x if x % 2 == 0 else -x for x in range(j, j + 3)] for j in range(k, k + 2)] for k in range(i, i + 3)] if i % 2 == 0 else {f"subkey_{k}": {f"inner_{n}": n if n % 3 == 0 else n * 2 for n in range(k, k + 3)} for k in range(i, i + 3)}) for i in range(1, 4)}

import pprint
pprint.pprint(bad_sample)

""" μ‹€ν–‰ κ²°κ³Ό:
{'key_1': {'subkey_1': {'inner_1': 2, 'inner_2': 4, 'inner_3': 3},
           'subkey_2': {'inner_2': 4, 'inner_3': 3, 'inner_4': 8},
           'subkey_3': {'inner_3': 3, 'inner_4': 8, 'inner_5': 10}},
 'key_2': [[[2, -3, 4], [-3, 4, -5]],
           [[-3, 4, -5], [4, -5, 6]],
           [[4, -5, 6], [-5, 6, -7]]],
 'key_3': {'subkey_3': {'inner_3': 3, 'inner_4': 8, 'inner_5': 10},
           'subkey_4': {'inner_4': 8, 'inner_5': 10, 'inner_6': 6},
           'subkey_5': {'inner_5': 10, 'inner_6': 6, 'inner_7': 14}}}
"""

참고자료:

https://wikidocs.net/138214