파이썬 문자열, 리스트, 튜플, 딕셔너리 핵심 활용 가이드

파이썬 프로그래밍의 핵심 요소인 문자열, 리스트, 튜플, 딕셔너리와 이들을 다루는 다양한 방법에 대해 자세히 알아봅니다. 각 데이터 타입의 특징과 효과적인 조작법을 이해하여 파이썬 코드를 더욱 유연하게 작성할 수 있습니다.

1. 문자열 (String) 다루기

1.1. 따옴표 사용의 차이

파이썬에서 문자열은 작은따옴표(''), 큰따옴표(""), 혹은 삼중 따옴표(""" """)로 정의할 수 있습니다. 문자열 내부에 특정 따옴표가 포함되어야 할 때 주로 그 용도가 구분됩니다.

  • 문자열 내부에 다른 따옴표가 없는 경우, 모든 따옴표의 기능은 동일합니다.
# 문자열에 특수문자가 없는 경우
text_a = '파이썬은 재미있습니다.'
text_b = "파이썬은 재미있습니다."
text_c = """파이썬은 재미있습니다."""
print(text_a)
print(text_b)
print(text_c)
# 출력:
# 파이썬은 재미있습니다.
# 파이썬은 재미있습니다.
# 파이썬은 재미있습니다.
  • 문자열 내부에 작은따옴표가 포함될 경우, 큰따옴표로 문자열을 감싸야 오류를 피할 수 있습니다.
# 문자열에 작은따옴표 포함 시
text_d = "오늘은 '특별한' 날입니다."
print(text_d)
# 출력:
# 오늘은 '특별한' 날입니다.
  • 여러 줄에 걸친 문자열을 정의하거나, 문자열 내부에 큰따옴표와 작은따옴표가 모두 포함될 경우 삼중 따옴표를 사용하는 것이 가장 일반적입니다.
# 여러 줄 문자열 또는 큰따옴표 포함 시
multi_line_text = """
파이썬은 다양한
"데이터 타입"을 지원합니다.
프로그래밍은 '재미있다'!
"""
print(multi_line_text)
# 출력:
#
# 파이썬은 다양한
# "데이터 타입"을 지원합니다.
# 프로그래밍은 '재미있다'!
#

1.2. 문자열 결합 (`+` 연산)

두 개 이상의 문자열은 + 연산자를 사용하여 하나로 합칠 수 있습니다.

part1 = "안녕, "
part2 = "파이썬!"
combined_string = part1 + part2
print(combined_string)
# 출력: 안녕, 파이썬!

1.3. 문자열 반복 (`*` 연산)

문자열에 정수를 곱하면 해당 문자열이 지정된 횟수만큼 반복됩니다.

repeated_phrase = "반복! " * 3
print(repeated_phrase)
# 출력: 반복! 반복! 반복!

1.4. 문자열 인덱싱 (Indexing)

문자열의 각 문자는 0부터 시작하는 인덱스를 통해 접근할 수 있습니다. 음수 인덱스는 문자열의 끝에서부터 역순으로 접근합니다.

sample_str = "programming"
print(f"첫 번째 문자 (인덱스 0): {sample_str[0]}")
print(f"세 번째 문자 (인덱스 2): {sample_str[2]}")
print(f"마지막 문자 (인덱스 -1): {sample_str[-1]}")
print(f"뒤에서 세 번째 문자 (인덱스 -3): {sample_str[-3]}")
# 출력:
# 첫 번째 문자 (인덱스 0): p
# 세 번째 문자 (인덱스 2): o
# 마지막 문자 (인덱스 -1): g
# 뒤에서 세 번째 문자 (인덱스 -3): i

1.5. 문자열 슬라이싱 (Slicing)

문자열의 특정 부분을 추출하려면 슬라이싱을 사용합니다. [시작_인덱스:끝_인덱스:스텝] 형식으로 지정하며, 끝_인덱스는 포함되지 않습니다.

sample_str = "PythonDevelopment"
print(f"처음 6글자 (인덱스 0부터 5까지): {sample_str[0:6]}") # 'Python'
print(f"인덱스 6부터 끝까지: {sample_str[6:]}") # 'Development'
print(f"전체 문자열 복사: {sample_str[:]}") # 'PythonDevelopment'
print(f"두 칸 간격으로 건너뛰며 인덱스 1부터 10까지: {sample_str[1:11:2]}") # 'yhndv'
# P(y)t(h)o(n)D(e)v(e)l(o)pment
#    1   3   5   7   9

1.6. 자주 사용되는 문자열 메서드

(1) 첫 글자 대문자화: capitalize()

문자열의 첫 문자를 대문자로, 나머지를 소문자로 변환합니다.

text = "hello python world"
print(text.capitalize())
# 출력: Hello python world

(2) 대소문자 반전: swapcase()

문자열 내의 대문자를 소문자로, 소문자를 대문자로 바꿉니다.

text = "PyThOn PrOgRaMmInG"
print(text.swapcase())
# 출력: pYtHoN pRoGrAmMiNg

(3) 각 단어 첫 글자 대문자화: title()

공백이나 특수 문자로 구분된 각 단어의 첫 글자를 대문자로 변환합니다.

text = "my python journey"
print(text.title())
# 출력: My Python Journey

text_with_special = "my-python_journey"
print(text_with_special.title())
# 출력: My-Python_Journey

(4) 문자열 중앙 정렬: center()

문자열을 지정된 총 길이 안에서 중앙에 배치하고, 남는 공간을 특정 문자(기본값은 공백)로 채웁니다.

text = "center"
print(f"'{text.center(20)}'")
# 출력: '        center        '
print(f"'{text.center(20, '*')}'")
# 출력: '*******center*******'

(5) 전체 대문자/소문자 변환: upper(), lower()

문자열의 모든 문자를 각각 대문자 또는 소문자로 변환합니다.

text = "MixEd CaSe"
print(text.upper())
# 출력: MIXED CASE
print(text.lower())
# 출력: mixed case

(6) 공백 제거: strip(), lstrip(), rstrip()

문자열의 양쪽 끝(strip()), 왼쪽(lstrip()), 또는 오른쪽(rstrip())에서 공백, 탭, 개행 문자 등을 제거합니다. 특정 문자를 인자로 주면 해당 문자를 제거할 수 있습니다.

text = "   \t whitespace example \n  "
print(f"'{text.strip()}'")
# 출력: 'whitespace example'
print(f"'{text.lstrip()}'")
# 출력: 'whitespace example \n  '
print(f"'{text.rstrip()}'")
# 출력: '   \t whitespace example'

(7) 문자열 대체: replace()

문자열 내의 특정 부분을 다른 문자열로 바꿉니다. 세 번째 인자로 교체 횟수를 지정할 수 있습니다.

sentence = "Learning Python is fun, Python is great."
print(sentence.replace("Python", "Java"))
# 출력: Learning Java is fun, Java is great.
print(sentence.replace("Python", "C++", 1)) # 첫 번째 'Python'만 교체
# 출력: Learning C++ is fun, Python is great.

(8) 문자열 분리: split()

지정된 구분자를 기준으로 문자열을 분리하여 리스트로 반환합니다. 구분자를 지정하지 않으면 공백을 기준으로 분리합니다.

data = "apple,banana,cherry"
print(data.split(','))
# 출력: ['apple', 'banana', 'cherry']

sentence = "This is a test sentence"
print(sentence.split()) # 공백 기준 분리
# 출력: ['This', 'is', 'a', 'test', 'sentence']

path = "root/user/documents/file.txt"
print(path.split('/', 2)) # 최대 2번만 분리
# 출력: ['root', 'user', 'documents/file.txt']

(9) 문자열 연결: join()

리스트나 튜플과 같은 이터러블(iterable) 객체의 요소들을 특정 문자열로 연결하여 하나의 문자열을 생성합니다.

words = ['hello', 'world', 'python']
print('-'.join(words))
# 출력: hello-world-python

tuple_elements = ('a', 'b', 'c')
print('::'.join(tuple_elements))
# 출력: a::b::c

(10) 부분 문자열 찾기: find(), index()

두 메서드 모두 부분 문자열이 시작되는 인덱스를 반환하지만, 부분 문자열을 찾지 못했을 때의 동작이 다릅니다.

  • find(): 찾지 못하면 -1을 반환합니다.
  • index(): 찾지 못하면 ValueError를 발생시킵니다.
target_str = "python programming"
print(f"찾는 'pro'의 시작 인덱스 (find): {target_str.find('pro')}")
# 출력: 7
print(f"찾는 'xyz'의 시작 인덱스 (find): {target_str.find('xyz')}")
# 출력: -1

print(f"찾는 'gram'의 시작 인덱스 (index): {target_str.index('gram')}")
# 출력: 9
try:
    print(f"찾는 'abc'의 시작 인덱스 (index): {target_str.index('abc')}")
except ValueError as e:
    print(f"index 오류 발생: {e}")
# 출력: index 오류 발생: substring not found

(11) 문자열 길이: len()

문자열의 총 문자 개수를 반환합니다.

my_string = "korean text"
print(f"문자열 길이: {len(my_string)}")
# 출력: 11

(12) 문자 출현 횟수: count()

문자열 내에서 특정 부분 문자열이 나타나는 횟수를 계산합니다.

long_text = "banana apple banana orange"
print(f"'banana' 출현 횟수: {long_text.count('banana')}")
# 출력: 2
print(f"'a' 출현 횟수: {long_text.count('a')}")
# 출력: 6

(13) 문자열 구성 확인: isalnum(), isalpha(), isdigit()

  • isalnum(): 문자열이 모두 영문자와 숫자로 구성되어 있으면 True.
  • isalpha(): 문자열이 모두 영문자로 구성되어 있으면 True.
  • isdigit(): 문자열이 모두 숫자로 구성되어 있으면 True.
s1 = "HelloWorld123"
s2 = "HelloWorld"
s3 = "12345"
s4 = "Hello World" # 공백 포함
print(f"'{s1}' isalnum? {s1.isalnum()}")
# 출력: True
print(f"'{s2}' isalpha? {s2.isalpha()}")
# 출력: True
print(f"'{s3}' isdigit? {s3.isdigit()}")
# 출력: True
print(f"'{s4}' isalnum? {s4.isalnum()}")
# 출력: False (공백 때문에)

1.7. 문자열 포매팅

문자열 안에 변수나 값을 삽입하여 새로운 문자열을 생성하는 방법입니다.

(1) format() 메서드 사용

  • 위치 기반: 중괄호 {}의 순서대로 값을 삽입합니다.
template_pos = "이름: {}, 나이: {}, 직업: {}"
print(template_pos.format("김철수", 25, "개발자"))
# 출력: 이름: 김철수, 나이: 25, 직업: 개발자
  • 인덱스 기반: 중괄호 안에 인덱스를 지정하여 값을 삽입합니다. 같은 값을 여러 번 사용할 수 있습니다.
template_idx = "첫째는 {0}, 둘째는 {1}, 그리고 다시 첫째는 {0}."
print(template_idx.format("사과", "바나나"))
# 출력: 첫째는 사과, 둘째는 바나나, 그리고 다시 첫째는 사과.
  • 키워드 기반: 중괄호 안에 키워드를 지정하고, format() 메서드에 키워드 인자를 전달하여 값을 삽입합니다.
template_kw = "상품명: {item_name}, 가격: {price}원"
print(template_kw.format(item_name="노트북", price=1200000))
# 출력: 상품명: 노트북, 가격: 1200000원

(2) % 연산자를 이용한 포매팅 (구식 방식)

C 언어 스타일의 포매팅 방식으로, 형식 지정자를 사용하여 값을 삽입합니다. %s (문자열), %d (정수), %f (실수) 등이 주로 사용됩니다.

# 예시 1: 여러 타입의 값 포매팅
user_name = "박영희"
user_age = 30
user_city = "서울"
profile_msg = """
--- 사용자 정보 ---
이름: %s
나이: %d세
거주지: %s
------------------
""" % (user_name, user_age, user_city)
print(profile_msg)
# 출력:
# --- 사용자 정보 ---
# 이름: 박영희
# 나이: 30세
# 거주지: 서울
# ------------------

# 예시 2: 퍼센트 기호 포함 (%%로 표기)
progress_val = 75
print("작업 진행률: %d%% 완료" % progress_val)
# 출력: 작업 진행률: 75% 완료

2. 연산자 및 논리 표현식

2.1. 논리 연산자 (`and`, `or`, `not`)

논리 연산자는 조건식이나 논리적 흐름을 제어할 때 사용됩니다.

(1) 비교 연산자와 함께 사용

일반적으로 부등식 등 비교 연산의 결과인 불리언(True/False) 값에 적용됩니다. 우선순위는 () > not > and > or 입니다.

print(f"1 > 5 and 10 < 20: {1 > 5 and 10 < 20}")
# 출력: 1 > 5 and 10 < 20: False (False and True = False)
print(f"5 > 1 or 10 < 20: {5 > 1 or 10 < 20}")
# 출력: 5 > 1 or 10 < 20: True (True or True = True)
print(f"not (10 > 5): {not (10 > 5)}")
# 출력: not (10 > 5): False (not True = False)
print(f"(1 > 2 and 3 < 4) or (4 > 5 and 2 > 1): {(1 > 2 and 3 < 4) or (4 > 5 and 2 > 1)}")
# 출력: (1 > 2 and 3 < 4) or (4 > 5 and 2 > 1): False ((False and True) or (False and True) = False or False = False)

(2) 논리값이 아닌 피연산자와 사용 (단락 평가, Short-circuit Evaluation)

파이썬에서는 0, None, False, 그리고 비어있는 컨테이너(빈 문자열 "", 빈 리스트 [], 빈 튜플 (), 빈 딕셔너리 {}, 빈 세트 set())는 논리적으로 False로 간주됩니다. 그 외의 모든 값은 True로 간주됩니다.

  • X and Y: XFalse로 평가되면 X를 반환하고, 아니면 Y를 반환합니다.
  • X or Y: XTrue로 평가되면 X를 반환하고, 아니면 Y를 반환합니다.
print(f"0 or 5: {0 or 5}")
# 출력: 0 or 5: 5 (0이 False이므로 뒤의 5를 반환)
print(f"10 or 0: {10 or 0}")
# 출력: 10 or 0: 10 (10이 True이므로 10을 반환)
print(f"'' or 'Hello': {'' or 'Hello'}")
# 출력: '' or 'Hello': Hello (빈 문자열이 False이므로 뒤의 'Hello'를 반환)
print(f"[1, 2] and 'data': {[1, 2] and 'data'}")
# 출력: [1, 2] and 'data': data ([1, 2]가 True이므로 뒤의 'data'를 반환)
print(f"[] and 'data': {[] and 'data'}")
# 출력: [] and 'data': [] (빈 리스트가 False이므로 빈 리스트를 반환)
print(f"not []: {not []}")
# 출력: not []: True (빈 리스트는 False이므로 not False = True)
print(f"not 'some_text': {not 'some_text'}")
# 출력: not 'some_text': False ('some_text'는 True이므로 not True = False)

3. 리스트 (List) 활용

리스트는 여러 종류의 데이터를 순서대로 저장할 수 있는 변경 가능한(mutable) 시퀀스 자료형입니다.

3.1. 리스트 요소 접근

문자열과 유사하게 인덱싱과 슬라이싱을 통해 리스트의 요소에 접근할 수 있습니다.

data_list = [10, 20, 'apple', ['nested', 'list'], 50]
# 인덱싱 (단일 요소 접근)
print(f"두 번째 요소 (인덱스 1): {data_list[1]}")
# 출력: 두 번째 요소 (인덱스 1): 20
print(f"네 번째 요소 (중첩 리스트, 인덱스 3): {data_list[3]}")
# 출력: 네 번째 요소 (중첩 리스트, 인덱스 3): ['nested', 'list']

# 슬라이싱 (부분 리스트 추출)
print(f"처음 세 요소: {data_list[0:3]}")
# 출력: 처음 세 요소: [10, 20, 'apple']
print(f"두 번째부터 네 번째까지: {data_list[1:4]}")
# 출력: 두 번째부터 네 번째까지: [20, 'apple', ['nested', 'list']]
print(f"두 칸 간격으로 전체: {data_list[::2]}")
# 출력: 두 칸 간격으로 전체: [10, 'apple', 50]

3.2. 리스트에 요소 추가

(1) 끝에 추가: append()

리스트의 가장 마지막에 단일 요소를 추가합니다.

items = ['pen', 'notebook']
items.append('eraser')
print(f"append 후: {items}")
# 출력: append 후: ['pen', 'notebook', 'eraser']

(2) 특정 위치에 삽입: insert()

지정된 인덱스 위치에 요소를 삽입합니다. 기존 요소들은 뒤로 밀려납니다.

items = ['pen', 'notebook']
items.insert(1, 'paper') # 인덱스 1에 'paper' 삽입
print(f"insert 후: {items}")
# 출력: insert 후: ['pen', 'paper', 'notebook']

(3) 다른 리스트 확장: extend()

다른 이터러블 객체(리스트, 튜플 등)의 모든 요소를 현재 리스트의 끝에 추가하여 확장합니다.

list_a = [1, 2]
list_b = [3, 4, 5]
list_a.extend(list_b)
print(f"extend 후: {list_a}")
# 출력: extend 후: [1, 2, 3, 4, 5]

3.3. 리스트 요소 삭제

(1) 특정 인덱스 요소 삭제 및 반환: pop()

지정된 인덱스의 요소를 삭제하고 그 값을 반환합니다. 인덱스를 지정하지 않으면 마지막 요소를 삭제하고 반환합니다.

my_list = ['A', 'B', 'C', 'D']
removed_item = my_list.pop() # 마지막 요소 'D' 삭제
print(f"pop 후: {my_list}, 삭제된 요소: {removed_item}")
# 출력: pop 후: ['A', 'B', 'C'], 삭제된 요소: D

removed_item_at_index = my_list.pop(0) # 인덱스 0의 요소 'A' 삭제
print(f"pop(0) 후: {my_list}, 삭제된 요소: {removed_item_at_index}")
# 출력: pop(0) 후: ['B', 'C'], 삭제된 요소: A

(2) 특정 값 요소 삭제: remove()

리스트에서 처음 발견되는 특정 값을 삭제합니다. 해당 값이 없으면 ValueError를 발생시킵니다.

my_list = ['apple', 'banana', 'cherry', 'apple']
my_list.remove('apple') # 첫 번째 'apple' 삭제
print(f"remove 후: {my_list}")
# 출력: remove 후: ['banana', 'cherry', 'apple']

(3) 인덱스 또는 슬라이스로 삭제: del

del 키워드를 사용하여 특정 인덱스의 요소나 슬라이스 범위를 삭제할 수 있습니다.

my_list = ['task1', 'task2', 'task3', 'task4']
del my_list[1] # 인덱스 1 요소 삭제
print(f"del 후 (단일): {my_list}")
# 출력: del 후 (단일): ['task1', 'task3', 'task4']

del my_list[0:2] # 슬라이스 범위 삭제
print(f"del 후 (슬라이스): {my_list}")
# 출력: del 후 (슬라이스): ['task4']

(4) 리스트 전체 비우기: clear()

리스트의 모든 요소를 삭제하여 빈 리스트로 만듭니다.

my_list = [1, 2, 3]
my_list.clear()
print(f"clear 후: {my_list}")
# 출력: []

3.4. 리스트 요소 수정

(1) 인덱싱으로 수정

특정 인덱스의 요소를 직접 새로운 값으로 할당하여 수정합니다.

scores = [85, 90, 78, 92]
scores[2] = 80 # 인덱스 2의 78을 80으로 변경
print(f"인덱스 수정 후: {scores}")
# 출력: 인덱스 수정 후: [85, 90, 80, 92]

(2) 슬라이싱으로 수정

슬라이싱을 통해 여러 요소를 한 번에 수정할 수 있습니다. 할당하는 값의 개수가 슬라이스 범위의 길이와 달라도 상관없으며, 이 경우 리스트의 길이가 변경될 수 있습니다.

letters = ['a', 'b', 'c', 'd', 'e']
letters[1:4] = ['X', 'Y', 'Z'] # 'b', 'c', 'd'를 'X', 'Y', 'Z'로 교체
print(f"슬라이스 수정 후: {letters}")
# 출력: 슬라이스 수정 후: ['a', 'X', 'Y', 'Z', 'e']

letters[1:4] = ['P'] # 'X', 'Y', 'Z'를 'P'로 교체 (리스트 길이가 줄어듦)
print(f"슬라이스 수정 후 (길이 변경): {letters}")
# 출력: 슬라이스 수정 후 (길이 변경): ['a', 'P', 'e']

(3) 슬라이싱 + 스텝으로 수정 (요소 개수 일치 필요)

스텝을 사용하여 슬라이싱한 경우, 할당하는 값의 개수는 슬라이싱된 요소의 개수와 정확히 일치해야 합니다.

numbers = [10, 20, 30, 40, 50, 60]
numbers[0:6:2] = [1, 3, 5] # 인덱스 0, 2, 4를 1, 3, 5로 변경
print(f"스텝 슬라이스 수정 후: {numbers}")
# 출력: 스텝 슬라이스 수정 후: [1, 20, 3, 40, 5, 60]

3.5. 리스트 요소 검색 및 정보 확인

(1) 반복문 (`for`)

리스트의 모든 요소를 순회하며 접근할 때 사용합니다.

planets = ['Mercury', 'Venus', 'Earth']
for p in planets:
    print(f"행성: {p}")
# 출력:
# 행성: Mercury
# 행성: Venus
# 행성: Earth

(2) 리스트 길이: len()

리스트에 포함된 요소의 총 개수를 반환합니다.

my_cart = ['milk', 'bread', 'eggs']
print(f"카트의 상품 수: {len(my_cart)}")
# 출력: 3

(3) 요소 출현 횟수: count()

리스트 내에서 특정 요소가 나타나는 횟수를 계산합니다.

votes = ['candidateA', 'candidateB', 'candidateA', 'candidateC', 'candidateB']
print(f"'candidateA' 득표수: {votes.count('candidateA')}")
# 출력: 2

(4) 리스트 정렬: sort()

리스트의 요소를 오름차순으로 정렬합니다. reverse=True 인자를 사용하면 내림차순으로 정렬됩니다. 리스트 자체를 변경합니다.

num_list = [9, 1, 5, 2, 8]
num_list.sort() # 오름차순 정렬
print(f"정렬 후: {num_list}")
# 출력: [1, 2, 5, 8, 9]

num_list.sort(reverse=True) # 내림차순 정렬
print(f"역정렬 후: {num_list}")
# 출력: [9, 8, 5, 2, 1]

(5) 리스트 순서 뒤집기: reverse()

리스트의 요소 순서를 역순으로 뒤집습니다. 리스트 자체를 변경합니다.

items = ['one', 'two', 'three']
items.reverse()
print(f"뒤집은 후: {items}")
# 출력: ['three', 'two', 'one']

3.6. 리스트 중첩 및 조작

리스트는 다른 리스트를 포함할 수 있으며, 중첩된 구조를 통해 복잡한 데이터를 표현할 수 있습니다.

nested_data = ['alpha', [1, 2, ['sub_item']], 'beta']
# 중첩된 리스트의 'sub_item'을 'NEW_SUB_ITEM'으로 변경
nested_data[1][2][0] = 'NEW_SUB_ITEM'
print(f"중첩 리스트 수정 후: {nested_data}")
# 출력: ['alpha', [1, 2, ['NEW_SUB_ITEM']], 'beta']

3.7. 리스트 중복 제거 (set 활용)

리스트의 중복된 요소를 제거하려면 set으로 변환한 후 다시 리스트로 변환하는 방법을 사용할 수 있습니다. 이 과정에서 요소의 순서는 유지되지 않을 수 있습니다.

duplicate_list = [1, 2, 3, 2, 1, 4, 5, 3]
unique_list = list(set(duplicate_list))
print(f"중복 제거 후: {unique_list}")
# 출력: [1, 2, 3, 4, 5] (순서는 실행 환경에 따라 달라질 수 있음)

4. 튜플 (Tuple) 활용

튜플은 리스트와 유사하지만, 한번 생성되면 요소를 변경하거나 추가/삭제할 수 없는 불변(immutable) 시퀀스 자료형입니다. "읽기 전용 리스트"와 같습니다.

4.1. 튜플 요소 접근

리스트와 동일하게 인덱싱과 슬라이싱을 통해 요소에 접근할 수 있습니다.

my_tuple = (10, 'text', (1, 2), 30, 'end')
print(f"두 번째 요소 (인덱스 1): {my_tuple[1]}")
# 출력: text
print(f"첫 세 요소: {my_tuple[0:3]}")
# 출력: (10, 'text', (1, 2))
print(f"인덱스 1부터 4까지 두 칸 간격: {my_tuple[1:5:2]}")
# 출력: ('text', 30)

4.2. 튜플의 불변성

튜플 자체는 불변하지만, 튜플 내부에 변경 가능한(mutable) 객체(예: 리스트, 딕셔너리)가 포함되어 있다면, 해당 내부 객체의 내용은 변경할 수 있습니다.

mutable_in_tuple = (1, 2, [3, 4], 5)
# mutable_in_tuple[0] = 99 # TypeError: 'tuple' object does not support item assignment
mutable_in_tuple[2].append(6) # 튜플 내부의 리스트 요소는 변경 가능
print(f"튜플 내부 리스트 수정 후: {mutable_in_tuple}")
# 출력: (1, 2, [3, 4, 6], 5)

4.3. range() 함수

range() 함수는 일련의 숫자를 생성하는 이터러블 객체를 반환하며, 주로 for 반복문에서 사용됩니다. Python 3.x에서는 리스트를 직접 반환하는 대신 range 객체를 반환하므로, 리스트로 변환하려면 list() 함수를 사용해야 합니다.

print(f"range(5) 결과: {range(5)}")
# 출력: range(0, 5)
print(f"list(range(5)) 결과: {list(range(5))}")
# 출력: [0, 1, 2, 3, 4]

5. 딕셔너리 (Dictionary) 활용

딕셔너리는 '키(key)'와 '값(value)'의 쌍으로 이루어진 변경 가능한(mutable) 비정렬(unordered) 자료형입니다. 키는 고유해야 하며 불변(immutable) 객체여야 합니다.

5.1. 딕셔너리 요소 추가

(1) 직접 키-값 할당

새로운 키에 값을 할당하면 요소가 추가됩니다. 이미 존재하는 키에 값을 할당하면 해당 키의 값이 수정됩니다.

user_profile = {'name': '김민준', 'age': 28}
user_profile['city'] = '부산' # 'city' 키가 없으므로 새로운 요소 추가
print(f"새 키-값 추가 후: {user_profile}")
# 출력: {'name': '김민준', 'age': 28, 'city': '부산'}

user_profile['age'] = 29 # 'age' 키가 있으므로 값 수정
print(f"기존 키 값 수정 후: {user_profile}")
# 출력: {'name': '김민준', 'age': 29, 'city': '부산'}

(2) setdefault() 메서드

setdefault(key, value)는 지정된 key가 딕셔너리에 없으면 value를 할당하여 추가하고, key가 이미 존재하면 아무것도 변경하지 않습니다.

config_data = {'theme': 'dark'}
config_data.setdefault('language', 'en') # 'language' 키가 없으므로 추가
print(f"setdefault(새 키) 후: {config_data}")
# 출력: {'theme': 'dark', 'language': 'en'}

config_data.setdefault('theme', 'light') # 'theme' 키가 있으므로 변경 없음
print(f"setdefault(기존 키) 후: {config_data}")
# 출력: {'theme': 'dark', 'language': 'en'}

5.2. 딕셔너리 요소 삭제

(1) 키로 삭제 및 값 반환: pop()

지정된 key에 해당하는 요소를 삭제하고 그 value를 반환합니다. 키가 없으면 KeyError를 발생시키며, 두 번째 인자로 기본값을 주면 키가 없을 때 기본값을 반환합니다.

student_info = {'id': 101, 'name': '이지은', 'major': '컴퓨터과학'}
removed_major = student_info.pop('major')
print(f"pop 후: {student_info}, 삭제된 값: {removed_major}")
# 출력: {'id': 101, 'name': '이지은'}, 삭제된 값: 컴퓨터과학

(2) 키로 삭제: del

del 키워드를 사용하여 특정 키에 해당하는 요소를 삭제합니다.

student_info = {'id': 101, 'name': '이지은', 'major': '컴퓨터과학'}
del student_info['id']
print(f"del 후: {student_info}")
# 출력: {'name': '이지은', 'major': '컴퓨터과학'}

(3) 임의의 요소 삭제 및 반환: popitem()

임의의 키-값 쌍을 삭제하고 (key, value) 튜플 형태로 반환합니다. Python 3.7+부터는 삽입 순서의 마지막 요소를 삭제합니다.

settings = {'volume': 70, 'brightness': 80, 'contrast': 50}
removed_setting = settings.popitem()
print(f"popitem 후: {settings}, 삭제된 쌍: {removed_setting}")
# 출력: {'volume': 70, 'brightness': 80}, 삭제된 쌍: ('contrast', 50)

(4) 딕셔너리 전체 비우기: clear()

딕셔너리의 모든 요소를 삭제하여 빈 딕셔너리로 만듭니다.

my_dict = {'a': 1, 'b': 2}
my_dict.clear()
print(f"clear 후: {my_dict}")
# 출력: {}

5.3. 딕셔너리 요소 검색

(1) 키로 직접 접근

대괄호 [] 안에 키를 넣어 해당 키의 값을 가져옵니다. 키가 존재하지 않으면 KeyError가 발생합니다.

product = {'name': '키보드', 'price': 85000}
print(f"상품 이름: {product['name']}")
# 출력: 키보
# print(product['stock']) # KeyError 발생

(2) get() 메서드

get(key, default_value)는 키에 해당하는 값을 반환합니다. 키가 없으면 None을 반환하거나, 두 번째 인자로 지정된 default_value를 반환하여 KeyError를 방지합니다.

product = {'name': '키보드', 'price': 85000}
print(f"상품 가격 (get): {product.get('price')}")
# 출력: 85000
print(f"상품 재고 (get, 없는 키): {product.get('stock')}")
# 출력: None
print(f"상품 재고 (get, 기본값): {product.get('stock', '재고 없음')}")
# 출력: 재고 없음

(3) 키, 값, 아이템 얻기: keys(), values(), items()

  • keys(): 딕셔너리의 모든 키를 뷰(view) 객체로 반환합니다.
  • values(): 딕셔너리의 모든 값을 뷰(view) 객체로 반환합니다.
  • items(): 딕셔너리의 모든 키-값 쌍을 (key, value) 튜플의 뷰(view) 객체로 반환합니다.
employee = {'id': 'EMP001', 'position': '엔지니어', 'salary': 6000}
print(f"모든 키: {employee.keys()}")
# 출력: dict_keys(['id', 'position', 'salary'])
print(f"모든 값: {employee.values()}")
# 출력: dict_values(['EMP001', '엔지니어', 6000])
print(f"모든 아이템: {employee.items()}")
# 출력: dict_items([('id', 'EMP001'), ('position', '엔지니어'), ('salary', 6000)])

(4) 반복문 (`for`)

딕셔너리를 직접 순회하면 키를 얻을 수 있습니다. items()를 사용하면 키와 값을 동시에 얻을 수 있습니다.

employee = {'id': 'EMP001', 'position': '엔지니어', 'salary': 6000}
print("--- 키 반복 ---")
for key in employee: # 또는 employee.keys()
    print(key)
# 출력:
# id
# position
# salary

print("--- 키와 값 동시 반복 ---")
for key, value in employee.items():
    print(f"{key}: {value}")
# 출력:
# id: EMP001
# position: 엔지니어
# salary: 6000

5.4. 딕셔너리 중첩

딕셔너리 안에 리스트나 다른 딕셔너리를 포함하여 복잡한 계층적 데이터를 구성할 수 있습니다.

company_data = {
    'departments': {
        'sales': {'employees': ['Jane Doe', 'John Smith'], 'budget': 100000},
        'HR': {'employees': ['Alice Brown'], 'budget': 50000}
    },
    'location': 'Seoul'
}
# sales 부서에 'Peter Jones' 추가
company_data['departments']['sales']['employees'].append('Peter Jones')
print(f"직원 추가 후: {company_data['departments']['sales']['employees']}")
# 출력: ['Jane Doe', 'John Smith', 'Peter Jones']

# HR 부서 예산 변경
company_data['departments']['HR']['budget'] += 10000
print(f"HR 예산 변경 후: {company_data['departments']['HR']['budget']}")
# 출력: 60000

5.5. 조건에 따른 딕셔너리 요소 삭제

딕셔너리를 순회하면서 요소를 직접 삭제하면 RuntimeError가 발생할 수 있습니다. 따라서 삭제할 키들을 별도의 리스트에 저장한 후, 반복이 끝난 뒤에 삭제하는 것이 안전합니다.

my_settings = {'setting_1': True, 'config_key': 'value', 'data_path': '/path', 'setting_2': False}
keys_to_delete = []
for k in my_settings:
    if 'setting' in k:
        keys_to_delete.append(k)

print(f"삭제할 키 목록: {keys_to_delete}")
# 출력: ['setting_1', 'setting_2']

for k in keys_to_delete:
    del my_settings[k]
print(f"삭제 후 딕셔너리: {my_settings}")
# 출력: {'config_key': 'value', 'data_path': '/path'}

5.6. fromkeys() 메서드

dict.fromkeys(iterable, value)는 새로운 딕셔너리를 생성합니다. iterable의 요소들을 새 딕셔너리의 키로 사용하고, 모든 키에 대해 동일한 value를 할당합니다. value가 생략되면 None이 기본값으로 사용됩니다.

keys_list = ['user_id', 'username', 'email']
# 기본값 None으로 딕셔너리 생성
default_users = dict.fromkeys(keys_list)
print(f"fromkeys(기본값 None) 후: {default_users}")
# 출력: {'user_id': None, 'username': None, 'email': None}

# 특정 값으로 딕셔너리 생성
initial_status = dict.fromkeys(['taskA', 'taskB'], 'pending')
print(f"fromkeys(기본값 'pending') 후: {initial_status}")
# 출력: {'taskA': 'pending', 'taskB': 'pending'}

# 주의: 변경 가능한 객체를 기본값으로 사용 시
# 모든 키가 동일한 리스트 객체를 참조하게 됩니다.
shared_list_dict = dict.fromkeys(['item1', 'item2'], [])
shared_list_dict['item1'].append('data')
print(f"shared_list_dict: {shared_list_dict}")
# 출력: {'item1': ['data'], 'item2': ['data']}

태그: python 문자열 리스트 튜플 딕셔너리

8월 8일 18:37에 게시됨