728x90

1. 숫자형(Numeric)
- 숫자형 데이터 타입은 수치 계산을 위한 기본적인 타입으로, 여러 종류의 숫자를 표현하고 처리할 수 있다.
- 숫자형은 정수, 실수, 복소수 세 가지 주요 타입읍로 나뉘며, 불리언(Boolean) 타입도 정수의 특수한 형태로 볼 수 있다.
1.1 정수(Int)
- 정수 타입은 소수점이 없는 숫자를 표현한다.
- Python 3에서 정수는 (가상)메모리가 허용하는 한 무한대의 크기를 가질 수 있다.
- 크기 제한이 없어 매우 큰 수 처리 가능 임의 정밀도 산술(arbitrary-precision arithmetic)
- 임의 정밀도 산술은 숫자의 크기가 미리 정해진 비트 수에 제한되지 안혹, 필요에 따라 동적으로 확장될 수 있는 방식
- 메모리가 허용하는 한 숫자가 얼마나 커지든 정확한 값을 저장하고 계산할 수 있는 방식
- 이는 Overflow 걱정 없이 연산이 가능하다는 장점이 있다.
- 다양한 진법으로 표현 가능
- 기본적인 산술 연산 지원
# 정수 선언
a = 42
negative_num = -100
zero = 0
# 임의 정밀도 산술(arbitrary-percision arithmetic)
small_number = 42
big_number = 10**100
print(f"\n10의 100승 (googol): {big_number}")
print(f"googol의 자릿수: {len(str(big_number))}") # 101자리 숫자
# 기본 산술 연산
x, y = 10, 3
# 덧셈, 뺄셈, 곱셈
print(f"\n{x} + {y} = {x + y}") # 13
print(f"{x} - {y} = {x - y}") # 7
print(f"{x} * {y} = {x * y}") # 30
# 나눗셈 (나눗셈 결과는 float이 됨)
print(f"{x} / {y} = {x / y}") # 3.3333333333333335
# 정수 나눗셈 (몫만 반환, 결과는 int)
print(f"{x} // {y} = {x // y}") # 3
# 나머지 연산
print(f"{x} % {y} = {x % y}") # 1
# 거듭제곱
print(f"{x} ** {y} = {x ** y}") # 1000
1.1.1 불리언(Boolean)
- 불리언 타입은 참(True), 거짓(False) 두 가지 값만 가지는 특수한 타입
- 기술적으로 정수(Int)형의 하위 클래스로 분류되지만, 그 특별한 목적때문에 종종 데이터 타입으로 분류
- True는 1
- False는 0
- 주로 논리형이라고 분류
- 논리 연산에 사용
- 조건문에서 흐름 제어에 활용
- https://docs.python.org/3/reference/datamodel.html#objects-values-and-types
# 불리언 값
t = True # 1에 해당
f = False # 0에 해당
# int의 하위 클래스
print(isinstance(True, int)) # True
print(True + True) # 2
print(True * 8) # 8
print(type(True)) # <class 'bool'>
# 논리 연산
print(True and False) # False
print(True or False) # True
print(not True) # False
# 다른 타입의 불리언 평가
print(bool(0)) # False 숫자 0은 False
print(bool(42)) # True 0이 아닌 모든 숫자는 True
print(bool("")) # False 빈 문자열은 False
print(bool("hello")) # True 비어있지 않은 문자열은 True
print(bool([])) # False 빈 리스트는 False
print(bool([1, 2])) # True 비어있지 않은 리스트는 True
1.2 실수(Float)
- 실수형은 소수점이 있는 숫자를 표현한다.
- Python에서는 IEEE 754 표준의 64비트 부동소수점 방식으로 실수를 저장
- 부호(Sign) : 1비트
- 지수(Exponent) : 11비트
- 가수(Mantissa 또는 Significand) : 52비트
- 약 15-17자릿수의 십진 정밀도를 제공
- 컴퓨터에서 실수는 이진수로 저장되는데, 일부 십진 소수는 이진수로 정확히 표현할 수 없다.
- 이로 인해 0.1 + 0.2 가 정확히 0.3이 되지 않는 현상이 발생
# 실수 선언
pi = 3.14159
negative = -0.001
integer_like = 42.0
# 지수 표기법
avogadro = 6.02e23 # 6.02 × 10²³
plancks_constant = 6.63e-34 # 6.63 × 10⁻³⁴
print(avogadro) # 6.02e+23
# 부동소수점 정밀도 문제
print(0.1 + 0.2) # 0.30000000000000004
print(0.1 + 0.2 == 0.3) # False
# 정밀한 계산이 필요할 때는 decimal 모듈 사용
from decimal import Decimal
print(Decimal('0.1') + Decimal('0.2')) # 0.3
1.3 복소수(Complex)
- 복소수 타입은 실수부와 허수부로 구성된 복소수를 표현한다.
- 허수부는 j 또는 J 접미사를 사용
- 실수부와 허수부 모두 float 타입
- 복소수 연산 지원
- 전기공학 및 회로 분석, 신호 처리와 푸리에 변환, 2D 공간, 컴퓨터 그래픽스 등에서 사용
# 복소수 선언
z1 = 2 + 3j
z2 = complex(4, -1) # 4 - 1j
# 복소수 속성과 메서드
print(z1.real) # 2.0 (실수부) real은 복소수의 실수부만 반환
print(z1.imag) # 3.0 (허수부) imag는 허수부의 계수만 반환
print(abs(z1)) # 3.605551275463989 (복소수의 크기, 절대값)
# 복소수의 절대값은 복소평면에서 원점 (0,0)으로부터의 거리를 의미
# |2 + 3j| = 루트(2^2 + 3^2) = 루트(13) -> 3.605....
# 복소수 연산
print(z1 + z2) # (6+2j)
print(z1 * z2) # (11+10j)
print(z1 / z2) # (0.23529411764705882+0.7647058823529411j)
2. None 타입
- 값의 부재를 나타내는 특별한 타입
- 다른 언어의 null, NULL, nil 등과 유사한 개념이지만, 완전히 동일하지는 않다.
- 유일성 : None은 NoneType의 유일한인스턴스다.
- Python 에서는 다른 NoneType을 생성할 수 없다.
print(type(None)) # <class 'NoneType'>
# 새로운 NoneType 객체를 생성할 수 없음
# NoneType() # 이렇게 호출하면 오류 발생
- 불변성 : None 객체는 변경할 수 없다.
- 이미 생성된 None 객체의 상태를 변경할수없다.
- None은 어떤 속성이나 메서드도 가지고 있지 않아 수정할 방법이 없다.
# None에 속성을 추가하려고 하면 오류 발생
try:
None.some_attribute = 42
except AttributeError as e:
print(f"오류: {e}") # 'NoneType' object has no attribute 'some_attribute'
- 싱글톤 : Python 내에서 단 하나의 인스턴스만 존재
- 프로그램 전체에서 None을 참조할 때마다 항상동일한메모리상의위치를 가리킨다.
# id() 함수는 객체의 메모리 주소를 반환합니다
print(id(None)) # 예: 140722992590544
print(id(None)) # 예: 140722992590544
a = None
b = None
print(id(a)) # 예: 140722992590544
print(id(b)) # 예: 140722992590544
print(a is b) # True - 정확히 같은 객체를 참조함
- 불리언 컨텍스트에서 False로 평가되지만 다른 False 값들과는 구별된다.
- No≠은 "값의 부재"를 나타내는 반면, 다른 값들은 실제 존재하는 값이다.
#0은 숫자 0이라는 실제 값
#""은 빈 문자열이라는 실제 값
#[]은 빈 리스트라는 실제 값
#False는 불리언 False라는 실제 값
print(type(None)) # <class 'NoneType'>
print(type(0)) # <class 'int'>
print(type("")) # <class 'str'>
print(type([])) # <class 'list'>
print(type(False)) # <class 'bool'>
# 동등성 비교
print(None == 0) # False
print(None == "") # False
print(None == []) # False
print(None == False) # False
- 함수에서 명시적인 반환값이 없을 때 자동으로 반환된다.
- 함수에서 return 문이 없거나, 값 없이 return 만 있으면 자동으로 No≠ 이 반환된다.
def say_hello():
print("Hello!")
# 명시적인 반환값 없음
result = say_hello()
print(result) # None
print(result is None) # True
3. 시퀀스형(Sequence Types)
- 여러 데이터를 순서대로 저장하는 Python의 데이터 타입
- 공통적인 특성과 연산을 공유하면서도, 각각 특별한 용도를 가지고 있다.
- 크게 불변(Immutable) 시퀀스와 가변(Mutable) 시퀀스로 나뉜다.
- 모든 시퀀스의 공통 특성
- 순서가 있음 : 요소들은 정의된 순서를 가지며, 이 순서는 유지된다.
- 인덱싱 : 0부터 시작하는 인덱스를 통해 개별 요소에 접근 가능
- 슬라이싱 : 시퀀스의 일부분을 추출할 수 있다.
- 길이 : ≤n() 함수로 요소의 개수를 알 수 있다.
- 반복 : 시퀀스는 반복문 (for 루프 등)에서 순회할 수 있다.
- 연결 : 같은 타입의 시퀀스를 연결할 수 있다. (+)
- 반복 복제 : 시퀀스를 정수 배만큼 반복 복제할 수 있다. (⋅)
- 멤버십 테스트 : ∈ 및 ¬∈ 연산자로 멤버십을 확인할 수 있다.
- 최소/최대 : min() 및 max()로 최소값과 최대값을 확인할 수 있다.
# 시퀀스 공통 연산 예시 (문자열 사용)
sequence = "Python"
# 인덱싱
print(sequence[0]) # 'P'
print(sequence[-1]) # 'n' (마지막 문자)
# 슬라이싱
print(sequence[1:4]) # 'yth'
print(sequence[:3]) # 'Pyt'
print(sequence[3:]) # 'hon'
print(sequence[::2]) # 'Pto' (간격 2로 슬라이싱)
# 길이
print(len(sequence)) # 6
# 연결
print(sequence + " Programming") # 'Python Programming'
# 반복 복제
print(sequence * 3) # 'PythonPythonPython'
# 멤버십 테스트
print('P' in sequence) # True
print('z' in sequence) # False
# 최대/최소 (아스키 코드 기준)
print(min(sequence)) # 'P'
print(max(sequence)) # 'y'
3.1 불변 시퀀스
- 생성 후에는 내용을 변경할 수 없는 시퀀스다.
- 불변성 덕분에 해시 가능하므로 딕셔너리의 키나 집합의 원소로 사용 가능
- 해시 : 임의 크기의 데이터를 고정된 크기의 값(일반적으로 정수)으로 변환하는 과정
- 마치 지문과 같아서, 각 개체마다 고유한 "디지털 지문"을 생성한다.
- 해시 가능하다는 표현은 해당 객체가 변하지 않는 해시 값을 가진다는 것을 의미
- 불변 시퀀스만 해시 가능한 이유는
- 해시 값은 객체의 내용을 기반으로 생성
- 객체가 변하면 해시 값도 변해야 한다.
- 하지만 딕셔너리나 집합에서는 처음 저장된 위치로 다시 찾아갈 수 있어야 한다.
- 문자열(str) : 문자의 시퀀스
- 튜플(tuple) : 임의 객체의 불변 시퀀스
- 바이트(bytes) : 0-255 범위의 정수(바이트)의 불변 시퀀스
3.1.1 문자열(Str)
- 유니코드 문자의 불변 시퀀스
- Python3에서 모든 문자열은 유니코드로 처리된다.
- 텍스트 처리에 최적화
- 풍부한 문자열 메서드 제공
- 작은따옴표 ('), 큰따음표("), 삼중따옴표(''' 또는 """) 사용 가능
# 문자열 생성
s1 = "Hello, World!"
s2 = 'Python Programming'
s3 = """This is a
multi-line
string."""
# 문자열 메서드
print(s1.upper()) # 'HELLO, WORLD!'
print(s1.lower()) # 'hello, world!'
print(s1.replace('Hello', 'Hi')) # 'Hi, World!'
print(s1.split(', ')) # ['Hello', 'World!']
print(' '.join(['Hello', 'Python'])) # 'Hello Python'
print(s1.find('World')) # 7 (시작 인덱스)
print(s1.count('l')) # 3 (문자 'l'의 개수)
print(s1.startswith('Hello')) # True
print(s1.endswith('!')) # True
print(" strip example ".strip()) # 'strip example'
# 문자열 포맷팅
name = "Alice"
age = 30
print(f"{name} is {age} years old.") # 'Alice is 30 years old.' (f-string, Python 3.6+)
print("{} is {} years old.".format(name, age)) # 'Alice is 30 years old.'
print("%s is %d years old." % (name, age)) # 'Alice is 30 years old.' (오래된 방식)
- 텍스트 데이터 처리, 파일 경로, URL 등의 표현, 사용자 입력 및 출력, 데이터 포맷팅 및 변환 등에 사용
3.1.2 튜플(Tuple)
- 한 번 생성되면 내용을 변경할 수 없다.
- 여러 타입의 요소를 포함할 수 있는 불변 시퀀스다.
- 소괄호()로 생성한다.
# 튜플 생성
point = (10, 20)
person = ("John", 30, "Developer")
single_item = (42,) # 요소가 하나인 튜플은 쉼표 필요
empty = ()
tuple_from_list = tuple([1, 2, 3]) # (1, 2, 3)
# 튜플 언패킹
name, age, job = person # 'John', 30, 'Developer'로 언패킹
x, y = point # 10, 20으로 언패킹
# 튜플 메서드 (불변이므로 제한적)
print(person.count(30)) # 1 (30이 나타나는 횟수)
print(person.index("John")) # 0 ("John"의 인덱스)
# 튜플 연산
combined = point + (30, 40) # (10, 20, 30, 40)
repeated = point * 3 # (10, 20, 10, 20, 10, 20)
# 네임드 튜플 (더 명확한 구조)
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x, p.y) # 10 20
3.1.3 바이트(Bytes)
- 0-255 범위의 정수를 포함하는 불변 시퀀스
- b 접두사를 사용하여 생성
- 텍스트가 아닌 이진 데이터 처리에 적합
- 파일 I/O, 네트워크 통신에 사용
# bytes 생성
b1 = b"hello" # 문자열 리터럴로 생성
b2 = bytes([65, 66, 67]) # 정수 리스트로 생성
b3 = bytes.fromhex('68 65 6c 6c 6f') # 16진수 문자열로 생성
# bytes는 불변 (수정 불가)
try:
b1[0] = 72 # TypeError 발생
except TypeError as e:
print(f"에러: {e}")
3.2 가변 시퀀스
- 생성 후에도 내용을 변경할 수 있는 시퀀스
- 리스트(list) : 임의 객체의 가변 시퀀스
- 바이트배열(bytearray) : 0-255 범위의 정수(바이트)의 가변 시퀀스
3.2.1 리스트(List)
- 여러 타입의 요소를 포함할 수 있는 가변 시퀀스
- 대괄호[]로 생성
- 동적으로 크기 조절 가능
- 요소 추가, 삭제, 변경 기능이 있다.
- 중첩 리스트와 다차원 데이터 표현이 가능하다.
# 리스트 생성
fruits = ["apple", "banana", "cherry"]
mixed = [1, "hello", 3.14, [1, 2]]
empty = []
list_from_str = list("Python") # ['P', 'y', 't', 'h', 'o', 'n']
# 요소 접근 및 수정
print(fruits[0]) # 'apple'
fruits[1] = "orange" # ['apple', 'orange', 'cherry']
# 리스트 메서드
fruits.append("grape") # ['apple', 'orange', 'cherry', 'grape']
fruits.insert(1, "blueberry") # ['apple', 'blueberry', 'orange', 'cherry', 'grape']
fruits.extend(["kiwi", "lemon"]) # ['apple', 'blueberry', 'orange', 'cherry', 'grape', 'kiwi', 'lemon']
last_fruit = fruits.pop() # 'lemon'을 반환하고 리스트에서 제거
fruits.remove("orange") # 'orange' 항목 제거
print("grape" in fruits) # True
fruits.sort() # 알파벳 순으로 정렬
fruits.reverse() # 리스트 역순으로 뒤집기
fruits_copy = fruits.copy() # 리스트 얕은 복사
fruits.clear() # 모든 항목 제거
# 리스트 컴프리헨션
numbers = [1, 2, 3, 4, 5]
squares = [x**2 for x in numbers] # [1, 4, 9, 16, 25]
even_squares = [x**2 for x in numbers if x % 2 == 0] # [4, 16]
3.2.2 바이트배열(Bytearray)
- 0-255 사이의 정수를 포함하는 가변 시퀀스
- bytearray()함수로 생성
# bytearray 생성
ba1 = bytearray(b"hello") # bytes에서 생성
ba2 = bytearray([65, 66, 67]) # 정수 리스트로 생성
ba3 = bytearray(5) # 지정된 크기의 0으로 초기화
# bytearray는 가변 (수정 가능)
ba1[0] = 72 # 'h'를 'H'로 변경
print(ba1) # bytearray(b'Hello')
4. 집합형(Set)
- 중복을 허용하지 않고 순서가 없는 요소들의 컬렉션을 표현하는 데이터 타입
- 가변 집합(set)과 불변 집합(frozenset)이 있다.
- 집합 연산을 지원
- 모든 집합(가변, 불변)은 오직 해시 가능한 객체만 요소로 포함할 수 있다.
- 집합은 중복 제거, 데이터 필터링과 비교등에 사용
4.1 집합(Set)
- 집합(set)은 중복되지 않은 해시 가능한 객체들의 가변 컬렉션
- 집합의 경우 해시 가능한 요소만 포함할 수 있다.
- 내부적으로 해시 테이블이라는 구조를 사용
- 이 구조는 각 요소의 해시 값을 기반으로 요소를 저장하고 검색
- 빠른 검색 속도(O(1))를 가지는 비결
- 요소를 추가하거나 제거할 수 있다.
- 해시 불가능
- 요소 추가 : add(), update() 메서드로 집합에 요소 추가 가능
- 요소 제거 : remove(), discard(), pop() 메서드로 집합에서 요소 제거 가능
- 집합 비우기 : clear() 메서드로 집합의 모든 요소 제거 가능
- 중요한 점은, 이미 집합 안에 들어있는 요소 자체를 수정할 수는 없다.
- 집합에 포함될 수 있는 요소는 모두 불변 객체(해시 가능한 객체)여야 하기 때문
# 중괄호를 사용한 집합 생성
fruits = {"apple", "banana", "cherry"}
# set() 생성자 사용
numbers = set([1, 2, 3, 2, 1]) # 중복은 자동으로 제거됨: {1, 2, 3}
# 빈 집합 생성 (빈 중괄호는 딕셔너리로 해석되므로 set() 사용)
empty_set = set()
# 문자열로부터 집합 생성 (각 문자가 요소가 됨)
char_set = set("hello") # {'h', 'e', 'l', 'o'} (중복 'l' 제거됨)
# 기본 집합 연산
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
# 합집합: a 또는 b에 있는 모든 요소
print(a | b) # {1, 2, 3, 4, 5, 6}
print(a.union(b)) # 같은 결과
# 교집합: a와 b 모두에 있는 요소
print(a & b) # {3, 4}
print(a.intersection(b)) # 같은 결과
# 차집합: a에는 있지만 b에는 없는 요소
print(a - b) # {1, 2}
print(a.difference(b)) # 같은 결과
# 대칭차집합: a 또는 b에 있지만, 둘 다에는 없는 요소
print(a ^ b) # {1, 2, 5, 6}
print(a.symmetric_difference(b)) # 같은 결과
# 부분집합 확인
print({1, 2}.issubset(a)) # True: {1, 2}는 a의 부분집합
print(a.issuperset({1, 2})) # True: a는 {1, 2}의 상위집합
s = {1, 2, 3}
# 요소 추가
s.add(4) # {1, 2, 3, 4}
# 여러 요소 추가
s.update([5, 6]) # {1, 2, 3, 4, 5, 6}
# 요소 제거 (요소가 없으면 KeyError 발생)
s.remove(6) # {1, 2, 3, 4, 5}
# 요소 제거 (요소가 없어도 오류 없음)
s.discard(7) # 변화 없음 (7이 없으므로)
# 임의의 요소 제거 및 반환
popped = s.pop() # 집합에서 임의의 요소 제거 후 반환
# 참고: 어떤 요소가 제거될지 예측 불가
# 모든 요소 제거
s.clear() # 빈 집합: set()
4.2 불변 집합(Frozenset)
- 불변집합(frozenset)은 불변이라는 점을 제외하면 일반 집합과 동일
- 생성 후에는 내용을 변경할 수 없다.
- 불변성, 해시 가능
- add(), remove(), discard(), pop(), clear(), update() 등 메서드 사용 불가
- 새로운 불변 집합을 생성하는 연산 (union, intersection 등)은 가능
# frozenset 생성
frozen = frozenset([1, 2, 3, 2]) # frozenset({1, 2, 3})
# 집합 연산 (결과는 새로운 frozenset)
a = frozenset([1, 2, 3])
b = frozenset([3, 4, 5])
# 합집합
print(a | b) # frozenset({1, 2, 3, 4, 5})
# 교집합
print(a & b) # frozenset({3})
# 차집합
print(a - b) # frozenset({1, 2})
# 대칭차집합
print(a ^ b) # frozenset({1, 2, 4, 5})
# 딕셔너리 키로 사용
settings = {
frozenset(["dark", "mode"]): True,
frozenset(["notifications"]): False
}
print(settings[frozenset(["dark", "mode"])]) # True
frozen = frozenset([1, 2, 3])
# frozen.add(4) # 오류: 'frozenset' object has no attribute 'add'
# 대신 새로운 frozenset 생성
new_frozen = frozen.union([4, 5]) # frozenset({1, 2, 3, 4, 5})
5. 매핑형(Mapping)
- 매핑형의 유일한 내장 매핑 타입은 딕셔너리(Dictionary)다.
5.1 딕셔너리(Dictionary)
- 키(key)와 값(value)의 쌍을 저장하는 가변적인 컬렉션
- 효율적인 데이터 검색, 업데이트 및 삭제를 위해 설계되었다.
- 특징
- 키-값 쌍 : 각 요소는 고유한 키와 그에 연결된 값으로 구성
- 키의 유일성 : 딕셔너리 내에서 키는 고유해야 한다. (중복 키 불가)
- 키 타입 제한 : 키는 반드시 해시 가능한(불변) 객체여야 한다. (문자열, 숫자, 튜플 등)
- 값 타입 자유 : 값은 어떤 타입의 객체든 될 수 있다. (불변 또는 가변)
- 가변성 : 생성 후에도 요소를 추가, 수정, 삭제할 수 있다.
- 순서 유지 : Python 3.7부터 딕셔너리는 삽입 순서를 유지한다.
- 데이터 구조화 및 DB 모델링, 그래프 표현 등에 사용
# 중괄호와 콜론을 사용한 방법
person = {"name": "John", "age": 30, "city": "New York"}
# dict() 생성자 사용
person = dict(name="John", age=30, city="New York")
# 키-값 쌍의 리스트로 생성
person = dict([("name", "John"), ("age", 30), ("city", "New York")])
# 딕셔너리 컴프리헨션 사용
squares = {x: x**2 for x in range(6)} # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# 빈 딕셔너리 생성
empty_dict = {}
empty_dict = dict()
person = {"name": "John", "age": 30, "city": "New York"}
# 값 접근
print(person["name"]) # "John"
# 키가 없는 경우 KeyError 발생
try:
print(person["country"]) # KeyError: 'country'
except KeyError as e:
print(f"오류: {e}")
# get() 메서드로 안전하게 접근 (키가 없으면 None 반환)
print(person.get("country")) # None
# get() 메서드에 기본값 지정
print(person.get("country", "Unknown")) # "Unknown"
# 값 수정
person["age"] = 31 # 기존 키의 값 수정
person["country"] = "USA" # 새 키-값 쌍 추가
# 여러 키-값 쌍 한번에 업데이트
person.update({"email": "john@example.com", "age": 32})
# 요소 삭제
del person["city"] # 특정 키-값 쌍 삭제
popped_value = person.pop("age") # 키-값 쌍 삭제 후 값 반환
last_item = person.popitem() # 마지막으로 삽입된 키-값 쌍 삭제 후 (키, 값) 튜플 반환
# 딕셔너리 비우기
person.clear() # 모든 요소 삭제
# Python 3.9 이상에서는 | 연산자 사용 가능
dict1 = {"a": 1, "b": 2}
dict2 = {"b": 3, "c": 4}
merged = dict1 | dict2 # {'a': 1, 'b': 3, 'c': 4} (충돌 시 오른쪽 값 사용)
# 이전 버전에서는 update() 또는 딕셔너리 언패킹
merged = {**dict1, **dict2} # {'a': 1, 'b': 3, 'c': 4}
# 기존 딕셔너리 수정
dict1 |= dict2 # dict1은 이제 {'a': 1, 'b': 3, 'c': 4}
728x90