# Chapter-04-03
# 시퀀스형
# 컨테이너(Container : 서로다른 자료형[List, tuple, collections.deque])
# 플랫(Flat : 한개의 자료형[str, bytes, bytearray, array.array, memoryview])
# 가변(list, bytearray, array, memoryview, deque)
# 불변(tuple, str, bytes)
1. 해시테이블과 해시 값
# 해시테이블
# Key에 Value를 저장하는 구조
# 파이썬의 Dict 자료형은 해시 테이블의 한 예시임
# 키 값의 연산 결과에 따라 Value에 직접 접근이 가능한 구조
# key 값을 해싱 함수에 넣어주면 -> 해시 주소가 나옴 -> 해시 주소를 통해 key에 대한 value를 참조할 수 있다.
# Dict의 구조를 살펴보자
print(__builtins__.__dict__)
# print: {'__name__': 'builtins', '__doc__': "Built-in functions, exceptions, and other objects.\n\nNotew...
# Hash 값 확인
t1 = (10, 20, (30, 40, 50))
t2 = (10, 20, [30, 40, 50])
print(hash(t1)) # Hash 값인 5737367089334957572를 출력함
print(id(t1)) # 궁금해서 추가해 본 코드. id 값은 1177497314232이 출력됨 -> Hash 값 != id값
#print(hash(t2)) # Error: List형은 가변형(Mutable)이기 때문에 Hash 값을 가질 수 없음.
2. Dict 고급(setdefault 함수)
# Dict형에서 Setdefault 함수 사용의 예제 What? : Tuple을 Dict로 바꾸어 주는 함수
# 참고로 Setdefault의 사용은 권장되고 있음
source = ( # 이중 Tuple, 이것을 어떻게 Dict로 바꿀 수 있을까?
('k1', 'val1'),
('k1', 'val2'),
('k2', 'val3'),
('k2', 'val4'),
('k2', 'val5'),
)
# k1과 k2를 key 값으로 설정하면 key 중복이 일어난다 -> 그러면 어떻게?
new_dict1 = {}
new_dict2 = {}
# No use Setdefault
for k, v in source:
if k in new_dict1:
new_dict1[k].append(v) # key 값에 v를 List형으로 추가한다
else:
new_dict1[k] = [v] # key 값에 value가 있다면(List형으로) List 내에 value를 추가해준다
print(new_dict1)
# print: {'k1': ['val1', 'val2'], 'k2': ['val3', 'val4', 'val5']}
# Use Setdefault
for k, v in source:
new_dict2.setdefault(k, []).append(v) # setdefault의 인자는 (key, 자료형)이다.
# 그리고 그 자료형을 그대로 참조(?)한다 -> append(v)를 사용할 수 있음
# new_dict2.setdefault(k, ()).append(v) <- Error: Tuple형에는 append함수가 없으므로
print(new_dict2) # 같은 결과값이 나오는 것을 알 수 있다
# print: {'k1': ['val1', 'val2'], 'k2': ['val3', 'val4', 'val5']}
3. Tuple -> Dict 주의할 점
# 주의
# Dictionary Comprehension을 사용하면 위와 같은 결과가 나오지 않는다
new_dict3 = {k: v for k, v in source}
print(new_dict3)
# print: {'k1': 'val2', 'k2': 'val5'}
# value 값을 덮어버렸기 때문