260105 [ Day 5 ] - Python (2)

TaeHyun·2026년 1월 5일

TIL

목록 보기
128/182

시작하며

오늘은 교육 2주 차의 첫날이다. 저번 교육 과정에서는 파이썬을 배우는데 2주 정도 걸렸던 것으로 기억하는데, 이번 과정에서는 오늘 파이썬 파트가 마무리되고 내일부터 데이터 분석에 대해서 배우기 시작한다.

리스트

  • 대괄호 안에 원소를 나열한 복합 자료형
  • 다양한 자료형의 원소를 가질 수 있음
    • 수, 문자열, 리스트, 튜플, 딕셔너리 등 다양한 객체 가능
  • 원소의 입력 순서를 유지하며 원소의 중복을 허용
  • 원소에 인덱스가 있으므로 인덱싱 / 슬라이싱 가능
  • mutable list 이므로 원소를 추가, 삭제 또는 변경 가능
li1 = [1, 2.0, '3']

type(li1) # list
dir(li1)

주요 메서드

  • append(x) : x를 리스트 마지막에 추가
  • extend(iter) : 이터러블을 리스트 마지막에 추가
  • insert(idx, x) : idx 위치에 x 삽입
  • remove(x) : x를 삭제
  • pop(idx) : idx 위치의 원소를 삭제 후 반환
  • sort() : 오름차순 정렬, 자료형이 섞여 있으면 에러 발생
  • reverse() : 순서를 뒤집음
  • index(x) : x의 첫번째 인덱스 반환, 없으면 에러 발생
  • count(x) : x의 개수 반환, 없으면 0 반환

리스트 연산자

  • in 키워드 오른쪽에 리스트 같이 반복 가능한 객체가 오면(이터러블)왼쪽에는 원소가 와야 함
  • 이터러블 : 리스트, 튜플, 넘파이 배열, 판다스 시리즈 등
print(li1 + li2) # [1, 2.0, '3', 1, 3, 5, 3]
print(li2 * 2) # [1, 3, 5, 3, 1, 3, 5, 3]
print(1 in li1) # True
print(3 in li1) # False

리스트 인덱싱

  • 인덱싱은 원소의 본래 자료형을 반환
li3 = [1, 2, '3', '4', ['가', '나', '다']]

print(li3[0]) # 1
print((li3[2])) # 3 (type = str)
print(li3[-1]) # ['가', '나', '다']

리스트 슬라이싱

  • 지정한 인덱스 범위의 원소를 리스트로 반환
li3[:4] # [1, 2, '3', '4']
li3[4:] # [['가', '나', '다']]

li3[4:][0][0] # '가'
li3[4][0] # '가'
  • 리스트는 대괄호 안에 정수 인덱스 또는 슬라이스만 가능, 리스트는 불가
# li[[0, 2]] # 팬시 인덱싱 불가능
[li3[0], li3[2]] # [1, '3']

range

  • 연속하는 정수 시퀀스를 반환
    • range 클래스로 생성한 객체의 자료형은 range
  • 실수를 지정하면 에러 발생
ints = range(6)

print(ints)
print(type(ints))
# range(0, 6)
# <class 'range'>
list(range(6))
# [0, 1, 2, 3, 4, 5]

list(range(1, 6))
# [1, 2, 3, 4, 5]

list(range(1, 6, 2))
# [1, 3, 5]

이중 콜론 연산자

  • 슬라이스에 간격을 추가한 것
li4 = list(range(6))

li4[1:4:2] # [1, 3]
li4[:4:2] # [0, 2]
li4[1::2] # [1, 3, 5]
li4[::2] # [0, 2, 4]

리스트 원소 추가, 삭제 및 정렬

리스트 원소 추가

  • list.append(x) : 지정한 객체를 리스트 마지막 원소로 추가
    • 인수는 한 개만 지정할 수 있음
    • 인수를 두 개 이상 지정하면 에러 발생
li4.append(6)
print(li4) # [0, 1, 2, 3, 4, 5, 6]

# append 메서드로는 한 번에 하나만 추가할 수 있음
li4.append([7, 8])
print(li4) # [0, 1, 2, 3, 4, 5, 6, [7, 8]]
  • 개별 추가 필요 시
li4.append(7)
li4.append(8)

# 리스트 결합은 원본 데이터에 반영하지 않으므로 원본에 반영하고 싶으면 재할당 필요
li4 = li4 + [7, 8]

# append 및 extend 메서드는 원본 리스트에 반영하므로 재할당하면 안됨
  • list.extend(iter) : 지정한 시퀀스(이터러블) 원소를 리스트 마지막 원소로 추가
    • 인수로 한 개의 시퀀스(이터러블)만 지정 가능
    • 인수를 두 개 이상 지정하면 에러 발생
li4.extend([7, 8])
print(li4) # [0, 1, 2, 3, 4, 5, 6, [7, 8], 7, 8]
  • list.insert(idx, x) : 지정한 인덱스 위치에 객체를 삽입
li4.insert(1, [7, 8])
print(li4) # [0, [7, 8], 1, 2, 3, 4, 5, 6, [7, 8], 7, 8]

해당 메서드들은 실행 결과를 리스트에 업데이트하고 None을 반환

리스트 원소 삭제

  • list.remove(x) : 지정한 원소를 리스트에서 한 번 삭제
    • 해당 원소가 여러 개라면 개수만큼 반복 실행해야 모두 삭제 가능
    • 리스트에 없는 원소를 지정하면 에러 발생
li4 # [0, [7, 8], 1, 2, 3, 4, 5, 6, [7, 8], 7, 8]
li4.count([7, 8]) # 2
# 반복문으로 특정 원소 삭제
n = li4.count([7, 8])

for i in range(n):
    li4.remove([7, 8])

li4 # [0, 1, 2, 3, 4, 5, 6, 7, 8]
  • list.pop(idx) : 지정한 인덱스 원소를 리스트에서 삭제 후 반환
    • 인수를 생략하면 마지막 원소를 삭제
    • 리스트에 없는 인덱스를 지정하면 에러 발생
# 인덱스 지정해서 삭제
li4.pop(6)
li4 # [0, 1, 2, 3, 4, 5, 7, 8]

# 인덱스 지정 생략 시 마지막 원소 삭제
li4.pop()
li4 # [0, 1, 2, 3, 4, 5, 7]

리스트 원소 변경

  • 인덱싱으로 변경
li4[0] = 6
li4 # [6, 1, 2, 3, 4, 5, 7]

li4[1] = [1, 2]
li4 # [6, [1, 2], 2, 3, 4, 5, 7]
  • 슬라이싱으로 변경
li4[1:3] = [2, 1]
li4 # [6, 2, 1, 3, 4, 5, 7]

# 원소의 개수가 달라도 가능
li4[3:4] = [3, 0]
li4 # [6, 2, 1, 3, 0, 4, 5, 7]
  • 리스트 슬라이싱 결과 리스트가 반환되는데 거기에 정수 스칼라를 할당하면 에러 발생
li4[4:5] = 1
# NameError: name 'li4' is not defined

리스트 원소 정렬

  • list.sort() : 리스트 원소를 오름차순 정렬
    • 원소의 자료형이 다르면 에러 발생
    • list.sort(reverse=True) : 내림차순 정렬
li4 # [6, 2, 1, 3, 0, 4, 5, 7]

li4.sort()
li4 # [0, 1, 2, 3, 4, 5, 6, 7]

# 내림차순 정렬
li4.sort(reverse=True)
li4 # [7, 6, 5, 4, 3, 2, 1, 0]
  • list.reverse() : 리스트 원소를 뒤집음
    • 자료형 달라도 상관없음
li1 # [1, 2.0, '3']

li1.reverse()
li1 # ['3', 2.0, 1]
  • sorted(list) : 인수의 원소를 오름차순 정렬한 결과를 반환
    • reverse=True 속성 지정 시 내림차순 정렬
li2 # [1, 3, 5, 3]
sorted(li2) # [1, 3, 3, 5]
li2 # [1, 3, 5, 3]

li2 = sorted(li2)
li2 # [1, 3, 3, 5]

튜플

  • immutable list 이므로 원소를 추가, 삭제 또는 변경할 수 없음

튜플 생성 및 변경

  • () 또는 tuple() 을 사용해서 생성
    • 원소를 소괄호로 묶지 않아도 튜플로 자동 패킹
tup = (1, 2.0, '3')
type(tup) # tuple
dir(tup)
  • 변경 시도 시 에러 발생
tup[2] # '3'
tup[2] = 3
# TypeError: 'tuple' object does not support item assignment
  • 튜플의 원소 변경
# 튜플 원소 변경
tup = list(tup)
type(tup) # list

tup[2] = 3
tup # [1, 2.0, 3]

tup = tuple(tup)
type(tup) # tuple
tup # (1, 2.0, 3)

집합

set1 = {3, 1, 2, 1}

set1 # {1, 2, 3}
type(set1) # set
dir(set1)
  • 집합의 원소는 해시(검색) 가능하고 변하지 않아야 한다는 특징이 있음
  • 생성 시 중복 원소를 제거하고 오름차순 정렬(수치형)
    • 데이터 정합성 확인(고유값)
    • 조인하기전 활용
li2 # [1, 3, 5, 3]
set2 = set(li2)
set2 # {1, 3, 5}
  • 인덱스가 없으므로 인덱싱 / 슬라이싱 불가능
set1[0]
# TypeError: 'set' object is not subscriptable
  • 집합 연산(교집합, 합집합, 차집합) 가능
# 교잡헙
set1 & set2 # {1, 3}

# 합집합
set1 | set2 # {1, 2, 3, 5}

# 차집합
set1 - set2 # {2}

딕셔너리

  • 중괄호를 열고 원소(키: 값)를 콤마로 나열
    • 키에 수와 문자열, 값에 다양한 자료형(수, 시퀀스, 딕셔너리 등)을 지정
    • dict 클래스로 딕셔너리를 생성할 때는 키와 값을 등호로 연결(키는 문자열만 가능)
dct = {'item': 'pants', 'size': 'XL'}
dct # {'item': 'pants', 'size': 'XL'}

dct_1 = dict(item='pants', size='XL')
dct_1 # {'item': 'pants', 'size': 'XL'}
# 딕셔너리의 키는 정수, 실수, 문자열 가능
dct_2 = {0: 1, 1: 2.0, 3:'3'}
dct_2 # {0: 1, 1: 2.0, 3: '3'}

# dict 클래스를 사용할 때 키는 문자열만 가능
dct_3 = dict(0=1, 1=2.0, 2='3')
# SyntaxError: expression cannot contain assignment, perhaps you meant "=="?
  • 원소의 입력 순서를 유지(Python 3.7 이후)하고 키의 중복을 허용하지 않음
    • 같은 키에 서로 다른 값을 할당하면 마지막에 할당한 값으로 업데이트
  • 인덱스가 없으므로 대괄호 안에 키를 지정하여 접근(원소명)
'item' in dct # True
'shop' in dct # False

# 딕셔너리에 없는 키를 대괄호 안에 지정하면 에러 발생
dct['item'] # 'pants'
dct['shop'] # KeyError

딕셔너리 주요 메서드

  • items() : 딕셔너리의 모든 키와 값을 튜플로 묶어서 반환
  • keys() : 딕셔너리의 모든 키를 반환
  • values() : 딕셔너리의 모든 값을 반환
dct.keys() # dict_keys(['item', 'size'])

딕셔너리 원소 추가, 삭제 및 변경

  • 원소 추가
dct['shop'] = 'A1'
dct # {'item': 'pants', 'size': 'XL', 'shop': 'A1'}
  • 원소 삭제
del dct['item']
dct # {'size': 'XL', 'shop': 'A1'}
  • 원소 변경
dct['shop'] = 'A2'
dct # {'size': 'XL', 'shop': 'A2'}

조건문

if 조건문 기본 구조

  • 지정한 조건 만족 여부에 따라 실행할 코드를 분기
  • 콜론 아래 코드는 반드시 들여쓰기 필요
  • else 블럭은 생략하거나 마지막에 한 번만 추가

if 조건문에 지정하는 조건 코드는 실행 결과로 True 또는 False를 스칼라로 반환해야 함

input()

  • input() : 사용자가 입력한 값을 문자열로 반환
score = input('점수 :') # 100
score # '100'
score = float(score)
score # 100.0
score >= 100 # True

if 조건문 실행

  • 실행할 코드가 한 줄이면 콜론 오른쪽에 붙여서 작성 가능
score = float(input('점수 :'))

if score >= 90:
    print('합격')
elif score >= 80:
    print('재검사')
else:
    print('불합격')
if score >= 90:
    print('합격')

if score >= 90: print('합격')

리스트로 비교 연산 실행

scores = list(range(60, 101, 10))
scores # [60, 70, 80, 90, 100]
scores >= 90
# TypeError: '>=' not supported between instances of 'list' and 'int'

scores[0] >= 90 # False
for i in range(len(scores)):
    if scores[i] >= 90:
        print(f'{i} : 합격')
    elif scores[i] >= 80:
        print(f'{i} : 재검사')
    else:
        print(f'{i} : 불합격')
# 0 : 불합격
# 1 : 불합격
# 2 : 재검사
# 3 : 합격
# 4 : 합격

삼항 연산자

  • 조건에 따라 값을 선택할 수 있는 표현식
  • 값1 if 조건1 else 값2
'합격' if scores[0] >= 90 else '재검사'

# else 뒤에 새로운 조건 사용 가능
'합격' if scores[0] >= 90 else '재검사' if scores[0] >= 80 else '불합격'

for 반복문

for문 기본 구조

  • 코드 블럭을 여러 번 반복 실행해야 할 때 사용
  • for문은 반복 실행할 범위가 정해져 있을 때 사용
  • for문의 범위는 주로 리스트, 튜플, 딕셔너리, 문자열 등 사용

for문 실행

menu = ['짜장면', '탕수욕', '깐풍기', '짬뽕밥', '전가복', '샥스핀']

for item in menu:
    print(item, '시킬까요?')
# 짜장면 시킬까요?
# 탕수욕 시킬까요?
# 깐풍기 시킬까요?
# 짬뽕밥 시킬까요?
# 전가복 시킬까요?
# 샥스핀 시킬까요?
  • 조건문 추가
for item in menu:
    print(item, '시킬까요?')
    if item in ['짜장면', '짬뽕밥']:
        print('-> 요리부터 주문합시다!')
    print('-> 다음 메뉴는 뭔가요?\n')

반복문 제어

  • continue : continue를 만나면 처음으로 돌아가서 다음 원소를 실행
for item in menu:
    print(item, '시킬까요?')
    if item in ['짜장면', '짬뽕밥']:
        continue
    print('-> 다음 메뉴는 뭔가요?\n')
  • break : break를 만나면 반복문을 중단
for item in menu:
    print(item, '시킬까요?')
    if item in ['전가복', '샥스핀']:
        break
    print('-> 다음 메뉴는 뭔가요?\n')

중첩 for문

for i in range(2, 10):
    print(f'=== {i} 단 ===')
    for j in range(1, 10):
        print(f'{i} X {j} = {i * j}')
    print()
print('반복문 실행 완료')

반복문 결과를 리스트로 생성

nums = range(1, 11)
sqrs = []

for i in nums:
    sqrs.append(i ** 2)

sqrs # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
  • 조건문 추가
nums = range(1, 11)
sqrs = []

for i in nums:
    if i % 2 == 0:
        sqrs.append(i ** 2)

sqrs # [4, 16, 36, 64, 100]
nums = range(1, 11)
sqrs = []

for i in nums:
    if i % 2 == 0:
        sqrs.append(i ** 2)
    else:
        sqrs.append(i * 2)

sqrs # [2, 4, 6, 16, 10, 36, 14, 64, 18, 100]

리스트 컴프리헨션

  • 기본 형태
[i ** 2 for i in nums]
  • 조건 추가
[i ** 2 for i in nums if i % 2 == 0]
  • 삼항 연산자 추가
[i ** 2 if i % 2 == 0 else i * 2 for i in nums]

enumerate()

  • 이터러블 객체의 인덱스와 원소를 튜플로 묶어서 반환
for idx, value in enumerate(menu):
    print(f'{idx + 1}번째 메뉴는 {value}입니다.')
# 1번째 메뉴는 짜장면입니다.
# 2번째 메뉴는 탕수욕입니다.
# 3번째 메뉴는 깐풍기입니다.
# 4번째 메뉴는 짬뽕밥입니다.
# 5번째 메뉴는 전가복입니다.
# 6번째 메뉴는 샥스핀입니다.

zip()

  • 여러개의 이터러블 객체들에서 같은 인덱스 원소를 튜플로 묶어서 차례대로 반환
price = [10000, 20000, 28000, 11000, 60000, 60000]

for i, j in zip(menu, price):
    print(f'{i}의 가격은 {j:,}원 입니다.')
# 짜장면의 가격은 10,000원 입니다.
# 탕수욕의 가격은 20,000원 입니다.
# 깐풍기의 가격은 28,000원 입니다.
# 짬뽕밥의 가격은 11,000원 입니다.
# 전가복의 가격은 60,000원 입니다.
# 샥스핀의 가격은 60,000원 입니다.
  • enumerate()zip() 같이 사용
for (idx, vlaue), p in zip(enumerate(menu), price):
    print(f'{idx + 1}번째 메뉴는 {vlaue}이고, 가격은 {p:,}원 입니다.')
# 1번째 메뉴는 짜장면이고, 가격은 10,000원 입니다.
# 2번째 메뉴는 탕수욕이고, 가격은 20,000원 입니다.
# 3번째 메뉴는 깐풍기이고, 가격은 28,000원 입니다.
# 4번째 메뉴는 짬뽕밥이고, 가격은 11,000원 입니다.
# 5번째 메뉴는 전가복이고, 가격은 60,000원 입니다.
# 6번째 메뉴는 샥스핀이고, 가격은 60,000원 입니다.

예외 처리

  • 반복문에서 에러 발생 시 반복문 중단
for i in nums:
    if i % 3 == 0:
        i = str(i)
    print(i ** 2)
# TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
  • 이처럼 예기치 않은 에러로 코드 실행이 중단되는 것을 방지
  • try : 정상적으로 실행할 코드 블럭을 추가
  • except : 에러가 발생했을 시 실행될 코드 추가
    • 에러 종류를 명시하면 해당 에러에 대해 코드를 실행
    • except 여러번 사용 가능(에러 종류별)
for i in nums:
    try:
        if i % 3 == 0:
            i = str(i)
        print(i ** 2)
    except:
        print('에러 발생')
# 1
# 4
# 에러 발생
# 16
# 25
# 에러 발생
# 49
# 64
# 에러 발생
# 100
  • Exception as e 사용
for i in nums:
    try:
        if i % 3 == 0:
            i = str(i)
        print(i ** 2)
    except Exception as e: # 에러 메시지를 출력하도록 설정
        print(e)
# 1
# 4
# unsupported operand type(s) for ** or pow(): 'str' and 'int'
# 16
# 25
# unsupported operand type(s) for ** or pow(): 'str' and 'int'
# 49
# 64
# unsupported operand type(s) for ** or pow(): 'str' and 'int'
# 100

while 반복문

  • 조건을 만족하는 동안 계속 반복 실행해야 할 때 사용
    • 실행 도충 break를 만나면 중단
i = 5
while i >= 0:
    print(i)
    i -= 1
# 5
# 4
# 3
# 2
# 1
# 0
while True:
    i += 1
    if i >= 10000:
        break
print(i) # 10000

사용자 정의 함수

사용자 정의 함수의 필요성

  • 당장 실행되는 코딩에 집중하면 같은 코드를 여러 번 중복할 가능성이 있음
  • 코드를 중복하면 코드가 길어지고 간단한 수정 작업이 복잡해짐

사용자 정의 함수의 기본 구조

  • 매개변수에 인수를 전달받아 실행한 값을 반환
  • 함수를 정의할 때 괄호 안에 나열한 것을 매개변수(parameter)라고 함
  • 함수를 실행할 때 매개변수에 등호로 전달하는 값을 인수(argument)라고 함
  • 함수 내에서 사용하는 변수는 지역 변수라고 함
  • 함수 실행 도중 return을 만나면 즉시 종료하며, return문을 생략하면 None을 반환
    • return문 오른쪽에 여러 값을 콤마로 나열하면 튜플 형태로 반환
def bmi(hgt, wgt):
    bmi = wgt / (hgt / 100) ** 2
    return bmi
  • 함수 괄호 안에 매개변수와 전달인수를 등호로 연결하는 코드
bmi(hgt=178, wgt=70)
  • 함수 괄호 안에 전달인수만 입력한 코드(순서가 바뀌면 결과도 바뀜)
    • 매개변수를 추가할 수 없는 인수도 있고, 매개변수를 생략하면 안되는 인수도 있음
bmi(178, 70)

기본값 설정, Hinting 및 독스트링

  • 매개변수 인수의 기본값 설정 가능
  • Hinting : 매개변수의 설명
  • 독스트링 : 함수에 대한 설명
def bmi(hgt, wgt:float=70) -> float:
    '''
    This function returns bmi from weight(kg) and height(cm)
    '''
    return wgt / (hgt / 100) ** 2

전달인수의 기본값이 없는 매개변수는 왼쪽에, 있는 매개변수는 오른쪽에 놓아야 함

lambda 표현식

  • 함수처럼 동작하는 일회성 한 줄 코드에 적합
  • () 로 사용하거나 변수에 할당하여 사용 가능
(lambda hgt, wgt: wgt / (hgt / 100) ** 2)(175, 70)

bmi2 = lambda hgt, wgt: wgt / (hgt / 100) ** 2
bmi2(175, 70)

map()

  • 반복 가능한 객체의 원소별로 지정한 함수를 반복 실행하고 반환
  • 첫 번째 인수는 반복 실행할 함수(람다 표현식) 두 번째 인수는 반복 실행할 범위
    • map 객체 반환(list 등으로 변환해야 확인 가능)
sqrs = map(lambda x: x**2, nums)
list(sqrs) # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

filter()

  • 지정한 조건을 만족하는 원소만 선택하여 반환
result = filter(lambda x: x % 2 == 0, nums)
list(result) # [2, 4, 6, 8, 10]

내장 함수명과 중복 문제

# 전역 변수 목록 확인방법(주피터 노트북 매직 명령어)
%whos

# 특정 타입만 확인 -v 다음에 Type 추가
%whos -v list

지역 변수, 전역 변수, 내장 함수 순으로 실행

sum(nums) # 55

def sum(x, y=0):
    for i in x:
        y -= i
    return y

sum(nums) # -55
# 전역 변수 삭제
del sum

sum(nums) # 55

가변 매개변수(위치 인수)

  • *args : 개수 제한이 없는 위치 인수를 튜플로 전달
def printArgs(*args):
    for i in args:
        print(i)

printArgs(1, 2, 3)
# 1
# 2
# 3

가변 매개변수(키워드 인수)

  • **kwargs : 개수 제한이 없는 키워드 인수를 딕셔너리로 전달
def printKwargs(**kwargs):
    for k, v in kwargs.items():
        print(f'{k}: {v}')

printKwargs(메뉴='순대국', 가격=9000, 평점=4.5, 위치='창동')
# 메뉴: 순대국
# 가격: 9000
# 평점: 4.5
# 위치: 창동

모듈 생성

  • 사용자 정의 함수 코드를 모듈(py 파일)로 저장하면 해당 함수를 필요할 때마다 import 할 수 있음

함수 → 모듈(py 파일) → 패키지(폴더) → 라이브러리

# 모듈 전체 불러오기
import myFuncs

# 별칭으로 모듈 불러오기
import myFuncs as mf

# 원하는 일부 함수만 가져오기
from myFuncs import bmi
myFuncs.bmi(175, 70)
mf.bmi(175, 70)
bmi(175, 70)

마치며

오늘 정말 상당히 많은 내용을 다뤘다. 이미 한 번 배웠던 내용들이 아니었으면 꽤나 힘들었을 것 같다. 내일부터 데이터 분석에 대해 배우기 시작하는데, NumPy랑 Pandas에 대해서는 파이썬 정도로 알고 있는 건 아니니까 집중해서 잘 배워야겠다.

profile
Hello I'm TaeHyunAn, Currently Studying Data Analysis

0개의 댓글