자료구조
# List
다중값을 저장, 순서가 있고 index가 자동으로 부여 (index는 0~1씩 증가) C++의 vector와 유사하다.
형식 : 리스트명 = [], 리스트명 = ['데이터','데이터','데이터']
인덱스
왼쪽->오른쪽 : 0,1,2,3,4,
오른쪽-> 왼쪽 :-4, -3, -2,-1
#-------------------------------------------------------
## 데이터 추가 : append()/ insert()/ extend()
menu = ["페르소나"]
menu.append("릴레이") # ['페르소나', '릴레이']
menu.insert(1, "마중물") # ['페르소나', '마중물', '릴레이']
menu.extend(["수필", "시각"]) # ['페르소나', '마중물', '릴레이', '수필', '시각']
append는 C++의 vector.push_back()과 비슷함.
insert를 통해 삽입하고 싶은 위치에 삽입 가능.
extend 함수로 한번에 여러 데이터 삽입 가능.
items = ["A", "B", "C", "B"]
items.remove("B") # ['A', 'C', 'B'] : 맨 처음 만나는 데이터만 삭제
last = items.pop() # items : ['A', 'C'] / last : 'B'
items.clear()
remove는 전달한 값과 같은 값을 갖는 요소를 삭제 함. 근데 맨 처음 만나는 데이터만 삭제.
pop()은 맨 뒤 요소 삭제. 마치 C++ queue.pop()
clear은 리스트의 데이터만 삭제. 메모리는 남아있음
## 데이터 위치(index) 및 동일 데이터 갯수 : index(x) / count(x) / len(리스트명)
# index(x): 리스트에서 값 x가 있는 첫 번째 위치(인덱스)를 반환. 없으면 오류 발생!!!!
# count(x): 리스트에 값 x가 몇 개 들어있는지 개수
tech = ["Python", "Java", "Python", "C"]
print(tech.index("Python")) # 맨 처음 만나는 데이터의 index만 반환
print(tech.count("Python")) # 2 출력
len은 C++의 v.size()랑 비슷함
## 정렬 및 뒤집기 : sort() / reverse()
# sort(): 리스트의 요소를 오름차순으로 정렬 / 주의 원본 데이터의 순서가 바뀐다.
# reverse(): 정렬과 상관없이 현재 리스트의 순서를 그대로 거꾸로 뒤집는다.
numbers = [3, 1, 4, 5, 2]
numbers.sort() # 오름차순 정렬 -> [1, 2, 3, 4, 5]
numbers.sort(reverse=True) # 내림차순 정렬 -> [5, 4, 3, 2, 1]
numbers.reverse() # 뒤집기 -> [5, 4, 3, 2, 1]
# 복사 : copy() / 리스트를 똑같이 복사하여 새로운 리스트를 생성
# => 원본 리스트를 보존하고 똑같은 복사본으로 작업하고 싶을 때 사용
original = [1, 2, 3]
clone = original.copy() # [1, 2, 3]
clone=original이라고만 하면 깊은 복사가 이루어져서 위험함. 복제본을 만드려면 반드시 copy()함수를 사용할것.
#Dictionary
"키(key) - 값(value)" 쌍으로 데이터를 저장하는 자료구조. C++의 map과 비슷함. 근데 value 값에 모든 타입이
올 수 있다.
#생성
# 데이터가 존재하는 딕셔너리 생성
platform_info = {
"name": "당목담글",
"slogan": "사람과 마음을 연결하는 세상에서 가장 따뜻한 이어읽기 플랫폼",
"components": ["페르소나", "마중물", "릴레이"]
}
# 빈 딕셔너리 생성
empty_dict = {}
empty_dict2 = dict()
#get()
# get()을 사요하는 경우
print(platform_info.get("launch_year")) # None 인덱스로 접근하면 오류발생
print(platform_info.get("launch_year", 2026)) # 2026
get()을 사용하면 없는 키 값을 읽을 때 오류가 나지 않는다.
# 전용 내장 함수
'''
keys(): 딕셔너리의 모든 Key만 모아서
values(): 딕셔너리의 모든 Value만 모아서
items(): 딕셔너리의 (Key, Value) 쌍을 튜플로 묶어서
=> 주로 반복문에서 사용
'''
#데이터 삭제
# pop(key): 특정 Key에 해당하는 쌍을 꺼내면서(반환) 삭제
# del 딕셔너리[key]: 특정 Key의 쌍을 바로 삭제
# clear(): 딕셔너리의 모든 데이터
sample = {"A": 1, "B": 2}
val = sample.pop("A") # {'B': 2} / val => 1
del sample["B"] # {}
sample = {"A": 1, "B": 2, "c": 2}
sample.clear() # {} => 딕셔너리는 그대로.. 내부 데이터(key:value)들만 삭제.
#많이 쓰이는 사례
### 딕셔너리 활용법
# setdefault()와 collections.defaultdict(초기값 자동 설정)
'''
딕셔너리를 사용할 때 가장 자주 하는 작업 중 하나
"존재하지 않는 키면 값을 0(또는 빈 리스트)으로 만들고,
이미 존재하는 키면 값을 업데이트하기"
'''
## setdefault(key, default) 활용 : 단어 빈도수(Count) 계산
words = ["릴레이", "마중물", "릴레이", "페르소나", "마중물", "릴레이"]
counter = {}
for word in words:
# 키가 없으면 0을 먼저 넣고, 있으면 원래 값에 +1
counter[word] = counter.setdefault(word, 0) + 1
# {'릴레이': 3, '마중물': 2, '페르소나': 1}
## defaultdict 활용
# collections 모듈의 defaultdict를 사용하면
# 아예 딕셔너리 생성 단계부터 "기본 데이터 타입"을 지정할 수 있다!!
# 존재하지 않는 키를 조회하면 자동으로 빈 리스트([])를 기본값으로 생성
from collections import deque, Counter, defaultdict
user_history = defaultdict(list) # defaultdict(list, {})
user_history["김철수"].append("수필 텍스트 읽기")
user_history["이영희"].append("목소리 기부 참여")
user_history["김철수"].append("이어읽기 플랫폼 접속")
'''
defaultdict(list, {'김철수': ['수필 텍스트 읽기',
'이어읽기 플랫폼 접속'],
'이영희': ['목소리 기부 참여']})
# 딕셔너리 컴프리헨션 (Dictionary Comprehension) : 내포리스트 형태
# 1. 구성 요소 리스트를 기반으로 {요소명: 글자수} 딕셔너리 생성
components = ["페르소나", "마중물", "릴레이"]
component_lengths = {comp: len(comp) for comp in components}
print(component_lengths)
#=> {'페르소나': 4, '마중물': 3, '릴레이': 3}
# 조건문(if)과 함께 사용하기 (글자 수가 3개인 것만 골라내기)
filtered_dict = {k: v for k, v in component_lengths.items() if v == 3}
#=> {'마중물': 3, '릴레이': 3}
# collections.Counter : 데이터의 개수를 세어서 딕셔너리 형태로 변환해 주는 파이썬 내장 라이브러리
# 주로 알고리즘 테스트나 데이터 분석에서 많이 사용
from collections import Counter
votes = ["페르소나", "릴레이", "페르소나", "마중물", "페르소나", "릴레이"]
voted_counter = Counter(votes)
# => Counter({'페르소나': 3, '릴레이': 2, '마중물': 1})
# 가장 많이 등장한 상위 N개 뽑기
print(voted_counter.most_common(1)) # [('페르소나', 3)]
## 딕셔너리 병합 및 수정 : update()
# 두 개의 딕셔너리를 하나로 합치거나, 여러 값을 한 번에 수정할 때 update() 메서드를 사용
# 겹치는 키가 있다면 새로 들어온 값으로
platform_base = {"name": "당목담글", "type": "플랫폼"}
platform_detail = {"type": "이어읽기 플랫폼", "launch_year": 2026}
platform_base.update(platform_detail)
# => {'name': '당목담글', 'type': '이어읽기 플랫폼', 'launch_year': 2026}
# => platform_base에 platform_detail을 덮어쓰기
#Tuple
형식 : TUPLE명 = (데이터, 데이터... )
특징 : 리스트 처럼 순서는 있지만 데이터에 재한 수정이 불가!!!
따라서 LIST보다 처리 속도가 빠르다!!
platform_core = ("페르소나", "마중물", "릴레이")
numbers = 1, 2, 3 # 도 가능
# => (1, 2, 3)
#주의사항 : 데이터가 1개만 존재하는 겨우 마지막에 반드시,를 붙여야 한다.
single_element = (5,)
not_a_tuple = (5) # 는 튜플이 아닌 그냥 정수로..
# => 5
sample = (10, 20, 30)
print(sample[0])
sample[0] = 99 # TypeError : 'tuple' object does not support item assignment
del sample[0] # TypeError : 'tuple' object does not support item assignment
## 튜플의 활용법
# 1. 다중 변수 할당
service, phrase = ("당목담글", "사람과 마음을 연결하는 세상에서 가장 따뜻한 이어읽기 플랫폼")
# service : "당목담글"
# phrase : "사람과 마음을 연결하는 세상에서 가장 따뜻한 이어읽기 플랫폼"
# 2. 변수의 값 교환
a = 10
b = 20
a, b =b, a
# a : 20
# b : 10
# 3. 함수 내에서 다중 값 반환
def get_platform_info():
name = "당목담글"
year = 2026
return name, year #dtype : tuple
result = get_platform_info() # ('당목담글', 2026)
# 튜플은 프로그램이 실행되는 동안 절대 변하면 안된느 값을 다룰때 많이 사용
# 예 : 1년의 12달, 위도와 경도, 플랫폼 고정 메뉴 이름,주민등록번호 등...
#Set
파이썬의 셋(Set, 집합)은 수학의 집합 개념을 코드로 구현한 자료구조
중복을 허용하지 않는다: 아무리 똑같은 값을 여러 번 넣어도 set 안에는 딱 하나
순서가 없다 (Unordered): 데이터가 들어간 순서를 기억하지 않기 때문에,
리스트처럼 인덱싱(set[0])으로 특정 값을 꺼낼 수 없다!!!
#생성
components = {"페르소나", "마중물", "릴레이", "페르소나"}
# **** 주의: 빈 set을 만들 때는 {}가 아닌 set()을 사용!!!
# 이유 : 빈 딕셔너리가 만들어지기 때문!!!
empty_set = set()
## 데이터 추가/삭제
'''
add(x): 요소 1개 추가
update([x, y]): 여러 요소 한 번에 추가 / 이 때 리스트, 튜플로 전달됨!
remove(x): 특정 요소 삭제 / 주의 : 삭제할 값이 없을 경우, 오류 발생!!
discard(x): 특정 요소 삭제 / 삭제할 값이 없어도 오류 발생 하지 않음(오류 무시!)
'''
tech = {"Python", "Java"}
tech.add("C++") # {'C++', 'Java', 'Python'}
tech.update(["Go", "Kotlin"]) # {'C++', 'Go', 'Java', 'Kotlin', 'Python'}
tech.remove("Java") # {'C++', 'Go', 'Kotlin', 'Python'}
# Set만의 특별한 함수들
## 수학적 집합 연산 : 교집합/ 차집합/ 합집합
set_A = {1, 2, 3, 4}
set_B = {3, 4, 5, 6}
# 교집합(iNTERSECTION)
print(set_A & set_B) # {3, 4}
print(set_A.intersection(set_B)) # {3, 4}
# 합집합 (union) : 만약 중복데이터가 있을 경우 하나만...
print(set_A | set_B) # {1, 2, 3, 4, 5, 6}
print(set_A.union(set_B)) # {1, 2, 3, 4, 5, 6}
#차집합(Diffence) : 아애의 경우, A에는 있지만 B에는 없는 경우
print(set_A - set_B) # {1, 2}
print(set_A.difference(set_B)) # {1, 2}
## **** 실무/알고리즘에서 Set을 사용하는 경우***
# 1. 리스트에서 중복 데이터 단 한 줄로 제거
duplicated_list = ["릴레이", "마중물", "릴레이", "페르소나", "마중물"]
unique_list = list(set(duplicated_list)) # ['릴레이', '페르소나', '마중물']
# 2. 특정 데이터가 존재하는지 확인 (in 연산자)
blacklist = {"user123", "bad_bot", "spammer"}
if "bad_bot" in blacklist:
print("접근을 차단합니다.") # 접근을 차단합니다.
# *** Set은 딕셔너리와 같은 원리(해시 테이블)로 동작하기 때문에
# 데이터가 1,000만 개가 있어도 단 한 번에 값을 찾아낸다!!!
#해시 테이블
'''
해시 테이블(Hash Table)에 대하여
"어떤 데이터(Key)를 주더라도 단 한 번에 그 위치를 찾아내는 마법의 저장소"
원리
해시 함수(Hash Function)라는 특별한 수학적 함수를 거쳐 데이터의 방 번호(인덱스)를 결정
1. Key입력 : 검색하거나 저장하고 싶은 데이터("bad_bot")
2. 해시함수 통과 : 해시 함수가 글자를 숫자로 이루어진 고유한 고윳값(해시 코드)으로 변환
3. 인덱스 변환 : 이 숫자를 배열의 크기로 나눈 나머지 등을 이용해 실제 저장될 방 번호(인덱스)를 구한다
4. 값 저장/조회 : 그 방 번호(버킷)에 데이터(Value)를 바로 저장, 추출
의 단계를 거친다.
'''
#실제 생활과 비교 설명
'''
책이 1,000만권이 있는 도서관에서 책을 찾을 경우,
리스트 처럼 1번 부터 찾기는 힘들다
하지만, 책 이름을 컴퓨터에서 검색하여 "3층 c열에 있다"라고 결과를 확인한 후,
찾으면 바로 찾을 수 있다.
컴퓨터에서 검색 : 해시 함수
이와 같은 과정이 해시 테이블
# 해시 테이블의 장점 : 빠르다!
# 해시 테이블의 단점 : 미리 공간을 만들어놓아야 하기 때문에 메모리를 많이 차지 한다!
'''
# 출력 : print()
# 입력 : input()
name = '파이쏭'
print(name)
print(f'변수를 이용할 경우 %s' % name)
# %s : 문자열, %d: 숫자
# 정수의 경우 : int()로, 소숫점일 경우 float()로 변환
# 기본값 (각각의 값을 출력할 때 공백으로 구분)
print("apple", "banana", "cherry")
# => 출력:apple banana cherry
# 구분 기호를 이용할 경우 : sep="구분자"
print("apple", "banana", "cherry", sep=" / ")
# => 출력: apple / banana / cherry
# 하나의 print()에서 줄바꿈 대신 공백을 붙여서 한 줄로 출력
print("Hello", end=" ")
print("World")
# => 출력: Hello World
# 자주 사용되는 출력 특수 문자(이스케이프 문자)
\n: 줄바꿈
\t: 탭(Tab)만큼 띄우기
\\: 역슬래시(\) 문자 자체를 출력
# 형식을 지정하여 출력할 경우 : f-string 활용
f-string : 파이썬에서 문자열 안에 변수 값을 바로 넣을 수 있게 해주는 문법. "formatted string" 코드의 가독성 때문에 추가된 기능
service_name = "당목담글"
slogan = "사람과 마음을 연결하는 세상에서 가장 따뜻한 이어읽기 플랫폼"
print(f"[{service_name}]은 {slogan}입니다.")
age = 20
# 1. 옛날 방식 (문자열 더하기) - 숫자는 str()로 형변환을 해야 해서 번거로움
print("내 나이는 " + str(age) + "살입니다.")
# 2. .format() 방식 - 문자열과 변수의 위치가 떨어져 있어 한눈에 보기 힘듦
print("내 나이는 {}살입니다.".format(age))
# 3. f-string 방식 - 직관적이고 직관적이며 간결함!
print(f"내 나이는 {age}살입니다.")
a = 10
b = 20
print(f"{a} + {b}의 결과는 {a + b}입니다.")
# => 10+20의 결과는 30입니다.
name = "python"
print(f"대문자로 변환: {name.upper()}")
# => 출력: 대문자로 변환: PYTHON
## 소수점 자리수 지정
pi = 3.1415926535
print(f"원주율: {pi:.2f}")
# => 소소정 두자리까지만 출력
#실제 데이터는 그대로 있고, 출력할 때만 두자리까지 출력
# 금융권등에서 통장에 출력하는 경우 많이 사용
# 통신사의 요금 청구서 출력시에도 사용됨
## 천 단위 콤마(,) 넣기
money = 5000000
print(f"잔액: {money:,}원")
# => 출력: 잔액: 5,000,000원
## 디버깅용 출력 (=) (파이썬 3.8 이상)
# 변수에 무슨 값이 들어있는지 빠르게 확인(디버깅)하고 싶을 때,
# 괄호 안에 변수명과 함께 =를 붙이면 '변수명=값' 형태로 알아서 출력
user_count = 125
print(f"{user_count=}")
# => 출력: user_count=125
## 정렬과 공백 채우기 (Alignment)
# 텍스트를 좌측, 우측, 또는 가운데로 정렬하고
# 남는 공간을 특정 문자로 채울수 있다
'''
:<[길이]: 좌측 정렬
:>[길이]: 우측 정렬
:^[길이]: 가운데 정렬
'''
text = "당목담글"
# 10칸의 공간을 만들고 정렬
print(f"|{text:<10}|") # 좌측 정렬 -> |당목담글 |
print(f"|{text:>10}|") # 우측 정렬 -> | 당목담글|
print(f"|{text:^10}|") # 가운데 정렬 -> | 당목담글 |
## 빈 곳을 원하는 문자로 채우기
# 방향 표시(<, >, ^) 앞에 원하는 문자를 넣으면,
# 공백 대신 그 문자로 빈 곳을 채운다
# 예: 가운데 정렬하고 남는 공간을 하이픈(-)으로 채우기
print(f"{text:-^20}")
# => 출력: --------당목담글--------
## 날짜 및 시간(datetime) 포맷팅
# datetime 모듈을 사용할 때, 번거롭게 .strftime() 메서드를 쓰지 않고
# f-string 안에서 곧바로 원하는 날짜/시간 형식으로 출력할 수 있다
# 연-월-일 시:분:초 형식으로 출력
from datetime import datetime
now = datetime.now() # now() 현재 시스템의 시간 추출 함수
print(f"현재 시간: {now:%Y-%m-%d %H:%M:%S}")
# => 출력: 현재 시간: 2026-07-09 09:41:01
## 중괄호 {} 문자 자체를 출력
# 중괄호를 두 번 연속({{, }}) 쓰면 출력 가능
group = "릴레이"
print(f"플랫폼 구성 요소: {{{group}}}")
# => 플랫폼 구성 요소: {릴레이}
## 따옴표가 겹치는 상황 해결
# => f-string 내부에서 딕셔너리(Dictionary)의 키를 조회할 때 자주 발생
# => f-string 바깥쪽 따옴표와 안쪽 따옴표를
# 서로 다른 종류(쌍따옴표/홑따옴표)로 사용
user = {"name": "김철수", "role": "페르소나"}
print(f"사용자 역할: {user['role']}") # 사용자 역할: 페르소나
# 에러 예
print(f"사용자 역할: {user["role"]}") # SyntextError 발생
## 진수(Binary, Hex) 변환 및 0 채우기
# => 숫자를 2진수, 8진수, 16진수로 바꾸거나,
# 지정한 길이만큼 앞자리를 0으로 채워야 할 때
number = 42
print(f"2진수: {number:b}") # 2진수: 101010
print(f"16진수: {number:x}") # 16진수: 2a
# 빈 자리는 0으로 채우기
page = 7
print(f"페이지 번호: {page:03d}") # 페이지 번호: 007
'파이썬' 카테고리의 다른 글
| 0713 ML/DL (0) | 2026.07.13 |
|---|---|
| 0710 Numpy (0) | 2026.07.10 |
| 0708 데이터 분석 및 시각화 (0) | 2026.07.09 |
| 0707 Pandas (0) | 2026.07.09 |
| 0706 Class (0) | 2026.07.08 |