Python

파이썬 딕셔너리(Dictionary)와 집합(Set) 완벽 가이드

헬로제이콥 2025. 5. 9. 17:25

파이썬 딕셔너리(Dictionary)와 집합(Set) 완벽 가이드 및

초간단 전화번호부 프로그램

파이썬에서 데이터를 효과적으로 관리하는 데 사용되는 또 다른 중요한 자료 구조로 딕셔너리(Dictionary)와 집합(Set)이 있습니다. 이들은 각각 고유한 특징과 용도를 가지고 있습니다.

1. 파이썬 딕셔너리 (Dictionary)

딕셔너리는 키(Key)와 값(Value)의 쌍으로 이루어진 데이터를 저장하는 자료 구조입니다. 각 키는 고유해야 하며, 키를 통해 해당 값을 빠르게 찾아올 수 있습니다. 딕셔너리는 중괄호 {}를 사용하여 생성하며, 키: 값 형태로 요소를 정의합니다. 파이썬 3.7 버전부터는 입력된 순서가 유지되지만, 그 이전 버전에서는 순서가 보장되지 않았습니다.

1.1. 딕셔너리 생성

Python
 
# 빈 딕셔너리 생성
empty_dict1 = {}
empty_dict2 = {}

# 초기값을 가진 딕셔너리 생성
person = {
    "name": "홍길동",
    "age": 30,
    "city": "서울"
}
scores = {"국어": 90, "영어": 85, "수학": 100}

print(f"빈 딕셔너리 1: {empty_dict1}")
print(f"빈 딕셔너리 2: {empty_dict2}")
print(f"개인 정보 딕셔너리: {person}")
print(f"점수 딕셔너리: {scores}")

1.2. 딕셔너리 사용법 (주요 기능)

  • 값 접근 (Value Access): 키를 사용하여 해당 값을 가져옵니다.
  • Python
     
    print(f"이름: {person['name']}") # 홍길동
    print(f"수학 점수: {scores.get('수학')}") # 100
    
    # .get() 메소드는 키가 없을 경우 None을 반환하거나 지정된 기본값을 반환 (오류 발생 X)
    print(f"직업: {person.get('job')}") # None
    print(f"직업 (기본값): {person.get('job', '알 수 없음')}") # 알 수 없음
    # print(person['job']) # 키가 없으면 KeyError 발생
    
  • 요소 추가 및 수정: 새로운 키-값 쌍을 추가하거나 기존 키의 값을 수정합니다.
  • Python
     
    person['job'] = '개발자' # 새로운 키-값 추가
    print(f"직업 추가 후: {person}")
    
    person['age'] = 31 # 기존 키의 값 수정
    print(f"나이 수정 후: {person}")
    
  • 요소 삭제:
    • pop(): 특정 키의 아이템을 삭제하고 그 값을 반환합니다.
    • popitem(): (Python 3.7+ 부터) 마지막으로 추가된 키-값 쌍을 삭제하고 반환합니다. 이전 버전에서는 임의의 쌍을 삭제.
    • del: 특정 키의 아이템을 삭제합니다.
    • clear(): 모든 아이템을 삭제하여 빈 딕셔너리로 만듭니다.
    Python
     
    removed_score = scores.pop("영어")
    print(f"삭제된 영어 점수: {removed_score}, pop 후 scores: {scores}")
    
    del person['city']
    print(f"del city 후 person: {person}")
    
    # scores.clear()
    # print(f"clear 후 scores: {scores}") # {}
    
  • 키, 값, 아이템(키-값 쌍) 가져오기:
    • keys(): 딕셔너리의 모든 키를 모아서 dict_keys 객체로 반환합니다.
    • values(): 딕셔너리의 모든 값을 모아서 dict_values 객체로 반환합니다.
    • items(): 딕셔너리의 모든 키-값 쌍을 모아서 dict_items 객체로 반환합니다.
    Python
     
    print(f"person의 모든 키: {person.keys()}")
    print(f"person의 모든 값: {person.values()}")
    print(f"person의 모든 아이템: {person.items()}")
    
    # dict_keys, dict_values, dict_items는 리스트처럼 반복문에서 사용 가능
    for key in person.keys():
        print(f"키: {key}")
    
  • 키 존재 확인: in 연산자를 사용하여 특정 키가 딕셔너리에 있는지 확인합니다.
  • Python
     
    print(f"'name' 키가 person에 있는가? {'name' in person}") # True
    print(f"'city' 키가 person에 있는가? {'city' in person}") # False (위에서 삭제됨)
    
  • 길이 확인: len() 함수로 딕셔너리의 아이템(키-값 쌍) 개수를 확인합니다.
  • Python
     
    print(f"person 딕셔너리의 아이템 개수: {len(person)}")
    
  • 반복: for 문을 사용하여 딕셔너리를 순회할 수 있습니다.
  • Python
     
    # 키를 순회 (기본)
    for key in person:
        print(f"{key}: {person[key]}")
    
    print("-" * 20)
    # 아이템(키, 값)을 함께 순회
    for key, value in person.items():
        print(f"{key}: {value}")
    

2. 파이썬 집합 (Set)

집합은 순서가 없고, 중복된 값을 허용하지 않는 요소들의 모음입니다. 수학에서의 집합 개념과 유사하며, 교집합, 합집합, 차집합 등의 연산이 가능합니다. 중괄호 {}를 사용하거나 set() 함수로 생성합니다.

주의: 빈 집합을 만들 때는 s = {}가 아니라 s = set()을 사용해야 합니다. s = {}는 빈 딕셔너리를 생성합니다.

2.1. 집합 생성

Python
 
# 빈 집합 생성
empty_set = set()

# 초기값을 가진 집합 생성
fruits = {"사과", "바나나", "딸기"}
numbers = {1, 2, 2, 3, 3, 3, 4} # 중복된 값은 자동으로 제거됨

print(f"빈 집합: {empty_set}")
print(f"과일 집합: {fruits}") # 순서는 다를 수 있음
print(f"숫자 집합 (중복 제거됨): {numbers}") # {1, 2, 3, 4} (순서는 다를 수 있음)

# 리스트나 튜플로부터 집합 생성 가능
list_to_set = set([1, 2, "hello", "hello"])
print(f"리스트로부터 생성된 집합: {list_to_set}") # {1, 2, 'hello'}

2.2. 집합 사용법 (주요 기능)

  • 요소 추가: add() 메소드를 사용하여 요소를 추가합니다. (이미 있는 요소면 변화 없음)
  • Python
     
    fruits.add("오렌지")
    print(f"add 후 fruits: {fruits}")
    fruits.add("사과") # 이미 있으므로 변화 없음
    print(f"add '사과' 후 fruits: {fruits}")
    
  • 여러 요소 추가: update() 메소드를 사용하여 여러 요소를 한 번에 추가합니다.
  • Python
     
    fruits.update(["망고", "포도", "바나나"])
    print(f"update 후 fruits: {fruits}")
    
  • 요소 삭제:
    • remove(): 특정 요소를 삭제합니다. 요소가 없으면 KeyError 발생.
    • discard(): 특정 요소를 삭제합니다. 요소가 없어도 오류 발생 안 함.
    • pop(): 임의의 요소를 삭제하고 그 값을 반환합니다. (빈 집합이면 KeyError)
    • clear(): 모든 요소를 삭제하여 빈 집합으로 만듭니다.
    Python
     
    fruits.remove("바나나")
    print(f"remove '바나나' 후 fruits: {fruits}")
    # fruits.remove("키위") # KeyError 발생
    
    fruits.discard("딸기")
    print(f"discard '딸기' 후 fruits: {fruits}")
    fruits.discard("키위") # 오류 없음
    print(f"discard '키위' 후 fruits: {fruits}")
    
    # popped_fruit = fruits.pop()
    # print(f"pop으로 삭제된 과일: {popped_fruit}, pop 후 fruits: {fruits}")
    
  • 집합 연산:
    • 합집합 (Union): | 연산자 또는 union() 메소드
    • 교집합 (Intersection): & 연산자 또는 intersection() 메소드
    • 차집합 (Difference): - 연산자 또는 difference() 메소드
    • 대칭 차집합 (Symmetric Difference): ^ 연산자 또는 symmetric_difference() 메소드 (합집합 - 교집합)
    Python
     
    set1 = {1, 2, 3, 4, 5}
    set2 = {4, 5, 6, 7, 8}
    
    print(f"합집합 (set1 | set2): {set1 | set2}")
    print(f"합집합 (set1.union(set2)): {set1.union(set2)}")
    
    print(f"교집합 (set1 & set2): {set1 & set2}")
    print(f"교집합 (set1.intersection(set2)): {set1.intersection(set2)}")
    
    print(f"차집합 (set1 - set2): {set1 - set2}")
    print(f"차집합 (set1.difference(set2)): {set1.difference(set2)}")
    
    print(f"대칭 차집합 (set1 ^ set2): {set1 ^ set2}")
    print(f"대칭 차집합 (set1.symmetric_difference(set2)): {set1.symmetric_difference(set2)}")
    
  • 요소 확인: in 연산자를 사용하여 특정 요소가 집합에 있는지 확인합니다.
  • Python
     
    print(f"'사과'가 fruits에 있는가? {'사과' in fruits}")
    
  • 길이 확인: len() 함수로 집합의 요소 개수를 확인합니다.
  • Python
     
    print(f"fruits 집합의 요소 개수: {len(fruits)}")
    
  • 반복: for 문을 사용하여 집합의 모든 요소를 순회할 수 있습니다. (순서는 보장되지 않음)
  • Python
     
    for fruit_item in fruits:
        print(f"과일: {fruit_item}")
    

3. 딕셔너리 vs 집합: 언제 무엇을 사용할까?

  • 딕셔너리 (Dictionary):
    • 키-값 쌍으로 데이터를 저장하고 싶을 때 (예: 사람의 정보 - 이름:홍길동, 나이:30).
    • 특정 키를 통해 값을 빠르게 찾고 싶을 때.
    • 데이터의 의미를 명확하게 표현하고 싶을 때 (키가 데이터의 레이블 역할).
  • 집합 (Set):
    • 중복 없이 항목들을 저장하고 싶을 때 (예: 방문한 도시 목록).
    • 데이터의 존재 여부를 빠르게 확인하고 싶을 때.
    • 여러 데이터 그룹 간의 수학적 연산(교집합, 합집합 등)이 필요할 때.
    • 순서가 중요하지 않을 때.

4. 초간단 전화번호부 프로그램 만들기 (딕셔너리 활용)

이름을 키(key)로, 전화번호를 값(value)으로 하는 딕셔너리를 사용하여 간단한 전화번호부 프로그램을 만들어 보겠습니다.

Python
 
# 전화번호부를 저장할 딕셔너리
phone_book = {}

while True:
    print("\n===== 초간단 전화번호부 프로그램 =====")
    print("1. 연락처 추가")
    print("2. 연락처 검색")
    print("3. 전체 연락처 보기")
    print("4. 연락처 수정")
    print("5. 연락처 삭제")
    print("6. 프로그램 종료")

    choice = input("원하는 작업의 번호를 입력하세요: ")

    if choice == '1':
        print("\n--- 연락처 추가 ---")
        name = input("이름: ")
        if name in phone_book:
            print(f"'{name}'은(는) 이미 등록된 이름입니다. 수정 메뉴를 이용해주세요.")
        else:
            phone_number = input("전화번호 (예: 010-1234-5678): ")
            phone_book[name] = phone_number
            print(f"'{name}'님의 연락처({phone_number})가 성공적으로 추가되었습니다.")

    elif choice == '2':
        print("\n--- 연락처 검색 ---")
        name = input("검색할 이름: ")
        if name in phone_book:
            print(f"이름: {name}, 전화번호: {phone_book[name]}")
        else:
            print(f"'{name}'에 해당하는 연락처를 찾을 수 없습니다.")

    elif choice == '3':
        print("\n--- 전체 연락처 보기 ---")
        if not phone_book: # phone_book 딕셔너리가 비어있으면 True
            print("저장된 연락처가 없습니다.")
        else:
            print("------------------------------")
            print(f"{'이름':<15} | {'전화번호':<15}")
            print("------------------------------")
            for name, phone_number in phone_book.items():
                print(f"{name:<15} | {phone_number:<15}")
            print("------------------------------")
            print(f"총 {len(phone_book)}개의 연락처가 있습니다.")

    elif choice == '4':
        print("\n--- 연락처 수정 ---")
        name = input("수정할 연락처의 이름: ")
        if name in phone_book:
            print(f"현재 '{name}'의 전화번호는 {phone_book[name]} 입니다.")
            new_phone_number = input("새로운 전화번호를 입력하세요: ")
            phone_book[name] = new_phone_number
            print(f"'{name}'의 전화번호가 '{new_phone_number}'로 수정되었습니다.")
        else:
            print(f"'{name}'에 해당하는 연락처를 찾을 수 없습니다.")

    elif choice == '5':
        print("\n--- 연락처 삭제 ---")
        name = input("삭제할 연락처의 이름: ")
        if name in phone_book:
            removed_number = phone_book.pop(name) # 삭제하고 값을 반환
            print(f"'{name}'({removed_number})님의 연락처가 삭제되었습니다.")
        else:
            print(f"'{name}'에 해당하는 연락처를 찾을 수 없습니다.")

    elif choice == '6':
        print("프로그램을 종료합니다. 이용해주셔서 감사합니다.")
        break # while 루프를 빠져나가 프로그램 종료

    else:
        print("잘못된 번호입니다. 메뉴에 있는 1~6 사이의 번호를 입력해주세요.")

프로그램 설명:

  1. phone_book = {}: 전화번호 정보를 저장할 빈 딕셔너리를 만듭니다. 이름이 키가 되고 전화번호가 값이 됩니다.
  2. while True:: 프로그램이 사용자의 종료 명령이 있을 때까지 계속 실행되도록 무한 루프를 만듭니다.
  3. 메뉴를 출력하고 사용자로부터 choice를 입력받습니다.
  4. if-elif-else 문을 사용하여 사용자의 선택에 따라 다른 작업을 수행합니다.
    • '1' (연락처 추가):
      • 이름과 전화번호를 입력받습니다.
      • 이미 등록된 이름인지 확인하고, 아니라면 phone_book 딕셔너리에 이름: 전화번호 쌍을 추가합니다.
    • '2' (연락처 검색):
      • 검색할 이름을 입력받습니다.
      • in 연산자로 해당 이름이 phone_book에 있는지 확인하고, 있으면 이름과 전화번호를 출력합니다. 없으면 없다고 알립니다.
    • '3' (전체 연락처 보기):
      • phone_book이 비어있는지 확인합니다.
      • 비어있지 않다면, items() 메소드와 for 루프를 사용하여 모든 이름과 전화번호를 보기 좋게 출력합니다.
    • '4' (연락처 수정):
      • 수정할 이름을 입력받습니다.
      • 이름이 존재하면 새로운 전화번호를 입력받아 해당 이름의 값을 업데이트합니다.
    • '5' (연락처 삭제):
      • 삭제할 이름을 입력받습니다.
      • 이름이 존재하면 pop() 메소드를 사용하여 해당 키-값 쌍을 딕셔너리에서 삭제합니다.
    • '6' (프로그램 종료):
      • break를 사용하여 while 루프를 탈출하고 프로그램을 종료합니다.
    • 그 외 (잘못된 입력):
      • 메뉴에 없는 번호를 입력하면 오류 메시지를 출력합니다.

이 프로그램은 파일 저장 기능은 없지만, 딕셔너리를 활용하여 기본적인 CRUD(Create, Read, Update, Delete) 기능을 갖춘 간단한 애플리케이션을 만드는 좋은 예시입니다.