본문 바로가기

Python/파이썬 - 기본을 갈고 닦자!

#17. dictionary(딕셔너리)

17. dictionary(딕셔너리)

 

17. dictionary(딕셔너리)

## 1. dictionary(딕셔너리) - 딕셔너리 타입은 immutable한 키(key)와 mutable한 값(value)으로 맵핑되어 있는 순서가 없는 집합입니다. - …

wikidocs.net

더보기
더보기
더보기

1. dictionary(딕셔너리)

  • 딕셔너리 타입은 immutable한 키(key)와 mutable한 값(value)으로 맵핑되어 있는 순서가 없는 집합입니다.
  • REPL에서 확인합니다.
  • 일반적인 딕셔너리 타입의 모습입니다. 중괄호로 되어 있고 키와 값이 있습니다.
>>> {"a" : 1, "b":2}
{'a': 1, 'b': 2}
  • 키로는 immutable한 값은 사용할 수 있지만, mutable한 객체는 사용할 수 없습니다.
# immutable 예
>>> a = {1: 5, 2: 3}   # int 사용
>>> a
{1: 5, 2: 3}
>>> a = {(1,5): 5, (3,3): 3} # tuple사용
>>> a
{(1, 5): 5, (3, 3): 3}
>>> a = { 3.6: 5, "abc": 3} # float 사용
>>> a
{3.6: 5, 'abc': 3}
>>> a = { True: 5, "abc": 3} # bool 사용
>>> a
{True: 5, 'abc': 3}

# mutable 예
>>> a = { {1, 3}: 5, {3,5}: 3}     #set 사용 에러
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'
>>> a = {[1,3]: 5, [3,5]: 3}     #list 사용 에러
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> a = { {"a":1}: 5, "abc": 3}     #dict 사용 에러
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
  • 값은 중복될 수 있지만, 키가 중복되면 마지막 값으로 덮어씌워집니다.
>>> {"a" : 1, "a":2}
{'a': 2}

  • 순서가 없기 때문에 인덱스로는 접근할수 없고, 키로 접근 할 수 있습니다.
>>> d = {'abc' : 1, 'def' : 2}
>>> d[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 0
>>> d['abc']
1
  • mutable 한 객체이므로 키로 접근하여 값을 변경할 수 있습니다.
>>> d['abc'] = 5
>>> d
{'abc': 5, 'def': 2}
  • 새로운 키와 값을 아래와 같이 추가할 수 있습니다.
>>> d['ghi'] = 999
>>> d
{'abc': 5, 'def': 2, 'ghi': 999}

2. dictionary(딕셔너리) 선언

  • 딕셔너리 선언할때는 빈 중괄호를 사용합니다.(set 중괄호를 이용하지만 빈중괄호로 선언하면 type이 dict가 됩니다.)
  • 딕셔너리로 명시적으로 선언할 수도 있습니다.
>>> e = {}
>>> type(e)
<class 'dict'>
>>> f = dict()
>>> type(f)
<class 'dict'>
  • dict constructor를 통해서 아래와 같이 바로 키와 값을 할당하며 선언할 수 있습니다.
>>> newdict = dict( alice = 5, bob = 20, tony= 15, suzy = 30)
>>> newdict
{'alice': 5, 'bob': 20, 'tony': 15, 'suzy': 30}

3. dictionary(딕셔너리) 변환

  • 리스트 속에 리스트나 튜플, 튜플속에 리스트나 튜플의 값을 키와 value를 나란히 입력하면, 아래와 같이 dict로 변형할 수 있습니다.
>>> name_and_ages = [['alice', 5], ['Bob', 13]]
>>> dict(name_and_ages)
{'alice': 5, 'Bob': 13}
>>> name_and_ages = [('alice', 5), ('Bob', 13)]
>>> dict(name_and_ages)
{'alice': 5, 'Bob': 13}
>>> name_and_ages = (('alice', 5), ('Bob', 13))
>>> dict(name_and_ages)
{'alice': 5, 'Bob': 13}
>>> name_and_ages = (['alice', 5], ['Bob', 13])
>>> dict(name_and_ages)
{'alice': 5, 'Bob': 13}

4. dictionary(딕셔너리) 복사

  • 얕은 복사(shallow copy) 1
>>> a = {'alice': [1, 2, 3], 'bob': 20, 'tony': 15, 'suzy': 30}
>>> b =a.copy()
>>> b['alice'].append(5)
>>> b
{'alice': [1, 2, 3, 5], 'bob': 20, 'tony': 15, 'suzy': 30}
>>> a
{'alice': [1, 2, 3, 5], 'bob': 20, 'tony': 15, 'suzy': 30}
  • 얕은 복사(shallow copy) 2
>>> a = {'alice': [1, 2, 3], 'bob': 20, 'tony': 15, 'suzy': 30}
>>> b = dict(a)
>>> a
{'alice': [1, 2, 3], 'bob': 20, 'tony': 15, 'suzy': 30}
>>> b
{'alice': [1, 2, 3], 'bob': 20, 'tony': 15, 'suzy': 30}
>>> id(a)
4334645680
>>> id(b)
4334648920
  • 깊은 복사(deep copy)
>>> import copy
>>> a = {'alice': [1, 2, 3], 'bob': 20, 'tony': 15, 'suzy': 30}
>>> b = copy.deepcopy(a)
>>> b['alice'].append(5)
>>> b
{'alice': [1, 2, 3, 5], 'bob': 20, 'tony': 15, 'suzy': 30}
>>> a
{'alice': [1, 2, 3], 'bob': 20, 'tony': 15, 'suzy': 30}

5. dictionary update(딕셔너리 수)

  • 단일 수정은 키로 접근하여 값을 할당하면 됩니다.
>>> a = {'alice': [1, 2, 3], 'bob': 20, 'tony': 15, 'suzy': 30}
>>> a['alice'] = 5
>>> a
{'alice': 5, 'bob': 20, 'tony': 15, 'suzy': 30}
  • 여러값 수정은 update 메소드를 사용합니다. 키가 없는 값이면 추가됩니다.
>>> a = {'alice': [1, 2, 3], 'bob': 20, 'tony': 15, 'suzy': 30}
>>> a.update({'bob':99, 'tony':99, 'kim': 30})
>>> a
{'alice': [1, 2, 3], 'bob': 99, 'tony': 99, 'suzy': 30, 'kim': 30}

6. dictionary(딕셔너리) for문

  • for문을 통해 딕셔너리를 for문을 돌리면 key값이 할당됩니다.
  • 순서는 임의적이다.같은 순서를 보장할 수 없다.
>>> a = {'alice': [1, 2, 3], 'bob': 20, 'tony': 15, 'suzy': 30}
>>> for key in a:
...     print(key)
... 
alice
bob
tony
suzy
  • value값으로 for문을 반복하기 위해서는 values() 를 사용해야합니다.
>>> for val in a.values():
...     print(val)
... 
[1, 2, 3]
20
15
30    
  • key와 value를 한꺼번에 for문을 반복하려면 items() 를 사용합니다.
>>> for key, val in a.items():
...     print("key = {key}, value={value}".format(key=key,value=val))
... 
key = alice, value=[1, 2, 3]
key = bob, value=20
key = tony, value=15
key = suzy, value=30

7. dictionary(딕셔너리) 의 in

  • dictionary의 in은 키에 한해서 동작합니다.
>>> 'alice' in a
True
>>> 'teacher' in a
False
>>> 'teacher' not in a
True

8. dictionary(딕셔너리)의 요소 삭제

  • list와 마찬가지로 del키워드를 사용합니다.
>>> a = {'alice': [1, 2, 3], 'bob': 20, 'tony': 15, 'suzy': 30}
>>> del a['alice']
>>> a
{'bob': 20, 'tony': 15, 'suzy': 30}

9. dictionary(딕셔너리)를 읽기 쉽게 표현해주는 pprint

  • pprint모듈로 dictionary를 찍어보자
Copy>>> from pprint import pprint as pp
>>> a = {'alice': [1, 2, 3], 'bob': 20, 'tony': 15, 'suzy': 30,"dodo": [1,3,5,7], "mario": "pitch"}
>>> print(a)
{'alice': [1, 2, 3], 'bob': 20, 'tony': 15, 'suzy': 30, 'dodo': [1, 3, 5, 7], 'mario': 'pitch'}
>>> pp(a)
{'alice': [1, 2, 3],
 'bob': 20,
 'dodo': [1, 3, 5, 7],
 'mario': 'pitch',
 'suzy': 30,
 'tony': 15}
문제 1. 다음 중 파이썬 딕셔너리의 키로 사용할 수 없는 것은 무엇입니까?
  1. 1
  2. (1, 2)
  3. 3.5
  4. [1, 2]
문제 2. 다음 코드의 출력 결과는 무엇입니까?
d = {"a": 1, "b": 2, "a": 3}
print(d)
  1. {'a': 1, 'b': 2}
  2. {'a': 3, 'b': 2}
  3. {'a': 3, 'b': 2, 'a': 1}
  4. 에러가 발생한다
문제 3. 다음 코드의 출력 결과는 무엇입니까?
d = {'abc' : 1, 'def' : 2}
print(d['abc'])
  1. 1
  2. 2
  3. None
  4. 에러가 발생한다
문제 4. 다음 코드의 출력 결과는 무엇입니까?
d = {'alice': [1, 2, 3], 'bob': 20}
d['alice'].append(4)
print(d)
  1. {'alice': [1, 2, 3], 'bob': 20}
  2. {'alice': [1, 2, 3, 4], 'bob': 20}
  3. {'alice': [1, 2, 3, 4]}
  4. 에러가 발생한다
더보기
더보기
더보기

4 2 1 2

  1. 정답: 4
    해설: 파이썬 딕셔너리의 키는 immutable(변경 불가능한) 자료형만 사용할 수 있습니다. 리스트는 mutable(변경 가능한) 자료형이므로 딕셔너리의 키로 사용할 수 없습니다.
  2. 정답: 2
    해설: 딕셔너리에서 동일한 키가 여러 번 사용되면, 마지막에 할당된 값이 저장됩니다. 따라서 {'a': 3, 'b': 2}가 출력됩니다.
  3. 정답: 1
    해설: 딕셔너리에서 키 'abc'에 해당하는 값은 1입니다. 따라서 1이 출력됩니다.
  4. 정답: 2
    해설: 딕셔너리에서 'alice' 키에 해당하는 값은 리스트이며, append 메서드를 사용하여 리스트에 4를 추가합니다. 따라서 {'alice': [1, 2, 3, 4], 'bob': 20}가 출력됩니다.
문제 5. 학생 성적 관리 시스템을 작성하세요.

다음은 학생들의 성적을 관리하는 간단한 프로그램을 작성하는 문제입니다. 이 프로그램은 학생들의 이름과 성적을 딕셔너리에 저장하고, 성적을 추가, 수정, 삭제, 조회하는 기능을 포함합니다.

요구사항

  1. 학생의 이름을 키(key)로 하고, 점수를 값(value)로 하는 딕셔너리를 사용합니다.
  2. 학생의 성적을 추가하거나 수정하는 함수 add_or_update_score를 작성합니다.
  3. 학생의 성적을 삭제하는 함수 delete_score를 작성합니다.
  4. 특정 학생의 성적을 조회하는 함수 get_score를 작성합니다.
  5. 모든 학생의 성적 평균을 계산하는 함수 calculate_average_score를 작성합니다.
# 테스트 케이스
grades = {}
add_or_update_score(grades, "Alice", 85)
add_or_update_score(grades, "Bob", 90)
add_or_update_score(grades, "Charlie", 78)
print("Grades:", grades)  # 출력: {'Alice': 85, 'Bob': 90, 'Charlie': 78}

delete_score(grades, "Alice")
print("Grades after deletion:", grades)  # 출력: {'Bob': 90, 'Charlie': 78}

print("Bob's score:", get_score(grades, "Bob"))  # 출력: 90
print("Alice's score:", get_score(grades, "Alice"))  # 출력: None

add_or_update_score(grades, "Bob", 95)
print("Grades after update:", grades)  # 출력: {'Bob': 95, 'Charlie': 78}

print("Average score:", calculate_average_score(grades))  # 출력: 86.5
더보기
더보기
더보기
def add_or_update_score(grades, name, score):
    """
    학생의 성적을 추가하거나 수정하는 함수입니다.
    
    :param grades: 학생 성적 딕셔너리
    :param name: 학생 이름 (문자열)
    :param score: 학생 성적 (숫자)
    """
    grades[name] = score

def delete_score(grades, name):
    """
    학생의 성적을 삭제하는 함수입니다.
    
    :param grades: 학생 성적 딕셔너리
    :param name: 학생 이름 (문자열)
    """
    if name in grades:
        del grades[name]

def get_score(grades, name):
    """
    특정 학생의 성적을 조회하는 함수입니다.
    
    :param grades: 학생 성적 딕셔너리
    :param name: 학생 이름 (문자열)
    :return: 학생 성적 (없을 경우 None 반환)
    """
    return grades.get(name)

def calculate_average_score(grades):
    """
    모든 학생의 성적 평균을 계산하는 함수입니다.
    
    :param grades: 학생 성적 딕셔너리
    :return: 성적 평균 (소수점 둘째 자리까지 반올림)
    """
    if not grades:
        return 0
    return round(sum(grades.values()) / len(grades), 2)

# 테스트 케이스
grades = {}
add_or_update_score(grades, "Alice", 85)
add_or_update_score(grades, "Bob", 90)
add_or_update_score(grades, "Charlie", 78)
print("Grades:", grades)  # 출력: {'Alice': 85, 'Bob': 90, 'Charlie': 78}

delete_score(grades, "Alice")
print("Grades after deletion:", grades)  # 출력: {'Bob': 90, 'Charlie': 78}

print("Bob's score:", get_score(grades, "Bob"))  # 출력: 90
print("Alice's score:", get_score(grades, "Alice"))  # 출력: None

add_or_update_score(grades, "Bob", 95)
print("Grades after update:", grades)  # 출력: {'Bob': 95, 'Charlie': 78}

print("Average score:", calculate_average_score(grades))  # 출력: 86.5
def add_or_update_score(grades, name, score):
    grades[name] = score
    return grades

def delete_score(grades, name):
    try:
        del grades[name]
    except KeyError:
        print("None")
    return grades

def get_score(grades, name):
    try:
        return grades[name]
    except KeyError:
        return "None"

def calculate_average_score(grades):
    sum_score = 0
    for score in grades.values():
        sum_score += score
    # average_score = sum(grades.values()) / len(grades)
    average_score = sum_score / len(grades)
    return average_score