객체를 복사하는 법
❗아래 코드에서 list1과 list2가 같은 객체를 공유하고 있기 때문에 한쪽을 수정하면 다른쪽도 영향을 받는다.
list1 = [1, 2, 3]
list2 = list1 # list1과 list2는 같은 객체를 공유
list2[0] = 10
print(list1) # 👉 [10, 2, 3] 출력됨
그렇다면 list1과 list2를 별개로 만드는 법은?
-> 복사를 하면 된다
# 방법 1: copy() 메서드
list2 = list1.copy()
# 방법 2: 슬라이싱
list2 = list1[:]
# 방법 3: list() 생성자
list2 = list(list1)
# 방법 4: copy 모듈의 deepcopy()
# (※ 리스트 안에 또 리스트가 있는 중첩 구조일 경우 필요)
import copy
list2 = copy.deepcopy(list1)
✅ 참고: 얕은 복사 vs 깊은 복사
| 복사 방식 | 중첩 구조(리스트 안에 리스트)에 안전한가? |
| copy() / [:] / list() | ❌ 얕은 복사 |
| copy.deepcopy() | ✅ 깊은 복사 (중첩까지 복사) |
round(반올림) 함수에 대해서
# 기본 문법
# round(number, ndigits)
# ㄴnumber : 반올림할 숫자
# ㄴndigits: 소수점 아래 몇 자리까지 반올림할지, 기본값은 0 (optional)
# 사용 예시 1 : 소수점없이 반올림
round(3.6) # 👉 4
round(3.2) # 👉 3
# 사용 예시 2: 소수점 아래 반올림
round(3.14159, 2) # 👉 3.14
round(2.675, 2) # 👉 2.67 (주의: 부동소수점 영향)
딥다이브) 왜 0.1 + 0.2가 0.3이 아닌 0.30000000000000004일까?
이유: 컴퓨터는 10진수를 2진수로 정확히 표현할 수 없음
- 0.1, 0.2는 2진수로 정확히 표현되지 않는 유리수예요.
- 마치 1/3이 무한소수 0.3333...처럼, 0.1은 2진수로 무한소수 → 근사값으로 저장됨.
- 그래서 계산하면 오차가 누적되어 0.30000000000000004 같은 결과가 나옴.
✅ 해결 방법
# 문제
print(0.1 + 0.2) # 0.30000000000000004
# 해결 방법 1: round() 함수로 반올림
print(round(0.1 + 0.2, 2)) # 👉 0.3
# 해결 방법 2: Decimal 모듈 사용 (정밀 계산)
from decimal import Decimal
a = Decimal("0.1")
b = Decimal("0.2")
print(a + b) # 👉 0.3
f-string의 기본 사용법 ( Python 3.6 이상 사용 가능 )
name = "Alice"
age = 25
print(f"My name is {name} and I am {age} years old.")
불리언 (bool)
print(bool(1)) # True
print(bool(0)) # False
print(bool(5)) # True (0이 아닌 모든 숫자는 True)
// 비어있지 않은 문자열, 리스트 등 = True
print(bool(123)) # True
print(bool("hello")) # True
print(bool([1,2])) # True
// 빈 문자열, 리스트 등 = False
print(bool(None)) # False
print(bool("")) # False
print(bool([])) # False
논리연산자
파이썬은 C/자바 스타일 논리 연산자(&&, ||, !)를 사용하지 않음
x = True
y = False
print(x and y) # False
print(x or y) # True
print(not x) # False
객체 비교
같은 객체냐, 같은 값을 가지고 있냐는 별개의 문제이므로, 비교하는 구문을 구분해서 사용해야한다.
# 객체 비교
list1 = [1, 2, 3]
list2 = [1, 2, 3]
list3 = list1
print(list1 == list2) # True (내용이 같음)
print(list1 is list2) # False (다른 객체)
print(list1 is list3) # True (같은 객체)
| 바교 | 의미 |
| == | 값(내용)이 같은가 |
| is | 동일한 객체인가 (id가 같은가) |
데이터 타입 변환하는 법
# 정수로 변환
int(3.14) # 3
# 실수로 변환
float(5) # 5.0
# 문자열로 변환
str(True) # "True"
# 불리언으로 변환
bool("Hello") # True
컬렉션 타입이란?
여러 값을 하나로 묶어서 저장할 수 있는 자료형
✅ 파이썬의 주요 컬렉션 타입
| 타입 | 형태 | 중복 허용 여부 | 특징 |
| 리스트(List) | [1, 2, 3] | ✅ 허용 | 순서 있음, 변경 가능 |
| 튜플(Tuple) | (1, 2, 3) | ✅ 허용 | 순서 있음, 변경 불가 |
| 집합(set) | {1, 2, 3} | ❌ 불허용 | 순서 없음, 중복 제거 |
| 딕셔너리(Dictionary) | {"a": 1, "b": 2} | ❌ 키 중복 불가 | 키-값 쌍, 순서 있음 (Python 3.7+) |
List 생성법
# 1. 대괄호로 생성
fruits = ["사과", "바나나", "체리"]
empty_list1 = []
# 2. list() 함수 사용
numbers = list(["사과", "바나나", "체리"])
empty_list2 = list()
리스트 컴프리헨션(List Comprehension)
기본 문법
[표현식 for 변수 in 반복가능한_객체]
[표현식 for 변수 in 반복가능한_객체 if 조건]
예제
squares = [x**2 for x in range(1, 6)]
# 👉 [1, 4, 9, 16, 25]
evens = [x for x in range(10) if x % 2 == 0]
# 👉 [0, 2, 4, 6, 8]
words = ["apple", "banana", "cherry"]
lengths = [len(word) for word in words]
# 👉 [5, 6, 6]
리스트 슬라이싱 (List Slicing)
# 리스트 접근과 슬라이싱
fruits = ["사과", "바나나", "체리", "딸기", "오렌지"]
# 슬라이싱: 범위 지정 [시작:끝:단계]
print(fruits[1:4]) # ['바나나', '체리', '딸기'] (1번부터 3번까지)
print(fruits[:3]) # ['사과', '바나나', '체리'] (처음부터 2번까지)
print(fruits[2:]) # ['체리', '딸기', '오렌지'] (2번부터 끝까지)
print(fruits[::2]) # ['사과', '체리', '오렌지'] (처음부터 끝까지 2단계씩)
print(fruits[::-1]) # ['오렌지', '딸기', '체리', '바나나', '사과'] (역순)
리스트 수정
# 리스트에서 특정 아이템을 명시해서 제거
fruits = ["사과", "바나나", "체리"]
fruits.remove("토마토") # "토마토"라는 항목이 없기 때문에 ERROR
결과: ValueError: list.remove(x): x not in list
.remove(x)는 리스트에 x가 없으면 ValueError 예외가 발생합니다.
✅ 해결 방법: 에러 안 나게 안전하게 제거하는 3가지 방법
1. if x in list: 로 체크 후 제거
✔️ 가장 일반적이고 명확한 방법
fruits = ["사과", "바나나", "체리"]
if "딸기" in fruits:
fruits.remove("딸기") # 딸기가 없으면 실행 안 함
2. try-except로 예외 처리
✔️ 여러 개의 항목을 반복 제거할 때 유용
try:
fruits.remove("딸기")
except ValueError:
pass # 없으면 그냥 넘어감
3. 리스트 컴프리헨션으로 새 리스트 만들기
✔️ 원본 리스트에서 "딸기"를 제거한 새 리스트를 만들기
fruits = [x for x in fruits if x != "딸기"]
✅ 참고)「i for」 vs「for i」
# 1. i for ... → 리스트 컴프리헨션
nums = [1, 2, 3, 4]
squares = [i**2 for i in nums]
# 2. for i, ... → 반복문에서 다중 변수 언패킹
pairs = [(1, 'a'), (2, 'b'), (3, 'c')]
for i, char in pairs:
print(i, char)
- i for ...는 리스트를 만들기 위한 표현식
new_list = [표현식 for 변수 in 반복가능한_객체] - for i, char in ...은 각 튜플을 자동으로 나누어 변수에 할당함
이걸 튜플 언패킹(unpacking)이라고 부른다.
| 구문 | 용도 | 예시 |
| i for i in ... | 리스트 컴프리헨션 | [i for i in range(5)] |
| for i, x in ... | 반복문에서 다중 변수 언패킹 | for i, x in enumerate(lst): |
enumerate
• 반환 형태 : (인덱스, 요소) 형태의 튜플을 반환
letters = ['a','b','c']
enum_obj = enumerate(letters)
# enumerate 리스트로 변환하기
print(list(enum_obj)) # {0: 'a', 1: 'b', 2: 'c'}
# ⚠️ enumerate는 한 번만 순회되는 이터레이터라서 list(enum_obj)를 하면 그 이후엔 비어 있음
print(list(enum_obj)) # {}
0부터 시작하는게 거슬리면 start옵션으로 인덱스 시작번호를 바꿀 수 있음
# index는 0부터 시작이지만 start=1로 지정 가능
# start 외 다른 옵션은 없음
for index, fruit in enumerate(fruits, start=1):
print(f"{index}번: {fruit}")
* zip
zip은 두 리스트의 요소를 순서대로 짝 지어 튜플로 만듬
# 여러 리스트 동시 순회 (zip과 함께 사용)
names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
for i, (name, score) in enumerate(zip(names, scores), start=1) :
print(f"학생 {i}: {name}, 점수: {score}")
# enumerate(..., 1)에서 1은 시작 인덱스를 의미 (1부터 카운팅)
예제 ) 할일 목록 관리
# 할 일 목록 (전역변수)
todo = []
# 할 일 추가
def add_task(task) :
print("---------add_task---------")
todo.append(task)
print(f"'{task}' 추가 완료")
# 할 일 목록 조회
def view_tasks() :
print("---------view_tasks---------")
for index, task in enumerate(todo, start=1) :
print(f"{index} 번째 할 일 : {task}")
# 할 일 완수
def complete_task(i) :
print("---------complete_task---------")
removed = todo.pop(i-1)
print(f"{i}번째 할 일 '{removed}'를 완수했습니다.")
# 프로그램 실행 예시
add_task("파이썬 공부하기")
add_task("장보기")
add_task("운동하기")
view_tasks()
complete_task(1) # "장보기" 완료
view_tasks()
중첩 리스트
리스트 컴프리헨션을 사용해서 중첩리스트 만드는 법
# 직접 생성
nested = [[1, 2, 3], [4, 5, 6]]
# 반복문으로 생성
rows, cols = 3, 4
# 리스트 컴프리헨션으로 생성 (더 간결한 방법)
matrix = [[i * cols + j for j in range(cols)] for i in range(rows)]
print(matrix)
# 결과
# [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
얕은 복사 vs 깊은 복사
✅ 얕은 복사의 문제점 예시 (shallow copy)
# 얕은 복사의 문제점 예시
original = [1, 2, [3, 4]]
shallow = original.copy()
# 내부 리스트 요소 변경
shallow[2][0] = 30
print(original) # [1, 2, [30, 4]] - 원본도 변경됨!
print(shallow) # [1, 2, [30, 4]]
✅ 깊은 복사 (deep copy)
import copy
original = [1, 2, [3, 4]]
deep = copy.deepcopy(original)
# 내부 리스트 요소 변경
deep[2][0] = 30
print(original) # [1, 2, [3, 4]] - 원본은 변경되지 않음
print(deep) # [1, 2, [30, 4]]
중첩 리스트 생성시 주의할 점
# 잘못된 방법
row = [0] * 3
bad_matrix = [row] * 3
bad_matrix[0][0] = 1 # 모든 행의 첫 번째 요소가 1로 변경됨
print(bad_matrix) # [[1, 0, 0], [1, 0, 0], [1, 0, 0]]
# 올바른 방법
good_matrix = [[0 for _ in range(3)] for _ in range(3)]
good_matrix[0][0] = 1
print(good_matrix) # [[1, 0, 0], [0, 0, 0], [0, 0, 0]]
왜 이런 차이가 생길까?
❌ bad_matrix = [row] * 3 는 "얕은 복사(shallow copy)"
- row 하나만 만들고 그걸 3번 반복해서 같은 객체를 참조한 상태
- 즉, bad_matrix[0], bad_matrix[1], bad_matrix[2]는 모두 같은 리스트 객체를 가리킴
✅ good_matrix는 "완전히 새로운 리스트 생성"
- for _ in range(3) 반복할 때마다 new list를 새로 만들어서 서로 다른 리스트 객체 3개를 생성
- 그래서 한 줄을 수정해도 다른 줄엔 영향이 없음.
참고) Python 코딩 규약 - PEP 8
✅ PEP 8이란?
Python Enhancement Proposal #8제목: "Style Guide for Python Code"파이썬 코드를 일관되고,
가독성 있게 작성하도록 규정한 문서
작성자: Guido van Rossum (파이썬 창시자 외)
▶ 변수는 소문자 + 밑줄(_)
user_name = "Alice"
total_count = 10
▶ 클래스 이름은 파스칼 케이스 (대문자 시작)
class UserProfile:
▶ 상수는 모두 대문자 + 밑줄
MAX_USERS = 100
PI = 3.14
✅ PEP 8은 여전히 파이썬의 공식 스타일 가이드이며, 최신이다.
Quiz
변수 Quiz)
# 문제 다음 코드의 출력 결과는 무엇인가요?
x = 10
y = 20
x, y = y, x
print(x, y)
변수 Quiz 정답)
데이터 타입 Quiz)
# 문제 1: 다음 코드의 출력 결과는 무엇인가요?
a = 0.1 + 0.1 + 0.1
b = 0.3
print(a == b)
# 문제 2: 다음 중 False로 평가되지 않는 것은 무엇인가요?
a) 0
b) ""
c) [0]
d) None
e) False
# 문제 3: 다음 코드의 실행 결과와 그 이유를 설명하세요.
text = "Python"
text[0] = "J"
print(text)
데이터 타입 Quiz 정답)
1. 부동소수점으로 인해 컴퓨터가 표현가능한 2진수의 한계가 있기 때문에, 내부적으로 근사치로 계산된다.
0.30000000000000004가 되므로 b = 0.3과 다르다고 판단됨.
2. 정답은 c. 비어있지 않은 리스트는 boolean 값이 True이다.
3. 문자열 str은 immutable(불변형) 자료형이기 때문에 인덱스를 이용해 직접 수정할 수 없음.
컬렉션 타입 - 리스트 Quiz 문제)
# 1. 다음 코드의 실행 결과는?
numbers = [1, 2, 3, 4, 5]
numbers[1:4] = [10, 20]
print(numbers)
# 2. 다음 코드의 실행 결과는?
def modify_list(lst):
lst.append(4)
lst = [7, 8, 9]
return lst
original = [1, 2, 3]
result = modify_list(original)
print(original)
print(result)
# 3. 다음 코드를 실행하면 어떤 오류가 발생할까요?
matrix = [[0] * 3] * 3
matrix[0][0] = 1
matrix[1][1] = 2
print(matrix)
컬렉션 타입 - 리스트 Quiz 정답)
1.
[1, 10, 20, 5]
2.
[1, 2, 3, 4]
[7, 8, 9]
3. 모든 행의 값이 동시에 바뀌어버림
[[1, 2, 0], [1, 2, 0], [1, 2, 0]]
과제
학생들의 이름과 점수 정보를 리스트로 관리하는 코드 구현
다음 기능을 구현하세요:
- 학생 추가: 이름과 점수를 입력 받아 목록에 추가
- 학생 삭제: 이름을 입력 받아 해당 학생 정보 삭제
- 성적 수정: 이름을 입력 받아 해당 학생의 점수 수정
- 전체 목록 출력: 모든 학생의 이름과 점수 출력
- 통계 출력: 최고 점수, 최저 점수, 평균 점수 계산 및 출력
본 후기는 [카카오엔터프라이즈x스나이퍼팩토리] 카카오클라우드로 배우는 AIaaS 마스터 클래스 (B-log) 리뷰로 작성 되었습니다.
'학습일지 > K-Digital Traing' 카테고리의 다른 글
| [KDT] AIaaS 마스터클래스 11주차 - 머신러닝 입문 (0) | 2025.06.04 |
|---|---|
| [KDT] AIaaS 마스터클래스 10주차 - Rest API와 FastAPI 활용 (2) | 2025.05.28 |
| [KDT] AIaaS 마스터클래스 8주차 - 리액트 상태관리와 Redux (1) | 2025.05.16 |
| [KDT] AIaaS 마스터클래스 8주차 - 이벤트 핸들링과 상태(state) (0) | 2025.05.15 |
| [KDT] AIaaS 마스터클래스 8주차 - 리액트 Hook (1) | 2025.05.14 |