본문 바로가기

PYTHON-BACK

#파이썬 기초 5일차_1

728x90

1. 바이트 자료형(bytes data type)

  • 파이썬 3 버전에 새로 추가된 자료형으로 컴퓨터가 기본으로 처리하는 바이트 자료형이다.
  • 저장되는 형태가 16진수의 Hexa 값으로 관리되고, ASCII 코드인 경우에는 Hexa 값 대신 문자로 보여 준다.
  • 바이트 자료형도 파이썬의 기본 문자열 자료형인 Unicode와 동일한 메서드를 가지고 처리되어진다.
  • 문자열 자료형처럼 변경이 불가능한 구조를 따르고 있다.

1.1 바이트 생성

  • 바이트 자료형의 생성은 리터널 형태로 b를 문자열 앞에 붙여서 표시한다.
  • bytes 생성자를 기반으로 인스턴스도 만들 수 있다.
a = 'hello'
print(type(a))

<class 'str'>

a = b'hello'
print(type(a))

<class 'bytes'>

 

  • 한글의 경우 2바이트 처리됨으로 b를 붙여서 바이트 형태로 바로 할 수는 없음
  • 따라서 한글의 경우 2바이트 문자를 1바이트 문자로 처리하는 단계를 거쳐야함
  • 아래 예시에서는 bytes라는 생성자를 통해서 encode 매소드를 통해 부호화작업으로 utf-8를 사용하여 
    문자를 부호화해서 바이트로 바꾸는 작업을 거쳐주었다. 
s = "대학교"
bs = bytes(s.encode("utf-8"))
print(type(bs))
print(bs)

<class 'bytes'>
b'\xeb\x8c\x80\xed\x95\x99\xea\xb5\x90'

print(bytes("대학교".encode("utf-8"))) # encode 결과물을 가져와서 넣어주는거고
print(bytes("대학교",encoding="utf-8")) # 생성자 속에서 결과물을 바꿔주는 방법

b'\xeb\x8c\x80\xed\x95\x99\xea\xb5\x90'

b'\xeb\x8c\x80\xed\x95\x99\xea\xb5\x90'

 

  • 복호화
print(bs.decode('utf-8'))

대학교

 

1.2 바이트 자료형의 메서드 확인

 

set 함수 : 중복되는 것은 나 없애고 동일한 것들만 들어가게 하는것

b = set(dir(bytes)) # bytes라는 클래스가 가지고있는 매소드와 정보 같은것
s = set(dir(str))

bs = b - s
print(bs)

{'fromhex', 'decode', 'hex'}

 

스트링 자체 리턴(스트링으로)한다는 것을 확인

bb = b"Hello"
bh = bb.hex() # bb를 16진수로 변환

print(type(bh), bh)

<class 'str'> 48656c6c6f

 

fromhex : 헥사 값을 이용해서 바이트를 만들어 사용하겠다.

bfh = bytes.fromhex('B901EF')
print(bfh)

b'\xb9\x01\xef'

 

1.3 encode/decode 메서드 처리

s = "가는 말이 고와야 오는 말이 곱다"
b = s.encode("utf-8")

print(type(b),b)
bs = b.decode("utf-8")
print(type(bs),bs)
print(bs)

<class 'bytes'> b'\xea\xb0\x80\xeb\x8a\x94 \xeb\xa7\x90\xec\x9d\xb4 \xea\xb3\xa0\xec\x99\x80\xec\x95\xbc \xec\x98\xa4\xeb\x8a\x94 \xeb\xa7\x90\xec\x9d\xb4 \xea\xb3\xb1\xeb\x8b\xa4'

<class 'str'> 가는 말이 고와야 오는 말이 곱다

가는 말이 고와야 오는 말이 곱다

 

  • 일부 복호화 해보면 제대로 인코딩 된것을 확인할 수 있었다.
print(b'\xea\xb0\x80\xeb\x8a\x94'.decode('utf-8'))

가는

 

1.4 bytes/str 생성자에서 직접 encode, decode 하기

  • 문자열, 생성자를 통해 인코드한 결과물은 형태와 결과물이 동일하다
s = "쌁휅휄뉅웱"
b = s.encode("utf-8") #문자열 인코드 결과물은 bytes 결과물을 출력 
bb = bytes(s, "utf-8") #생성자를 통해 인코드한 결과물은 bytes 결과물 출력 
print(b == bb)
print(str(bb, "utf-8"))

True

쌁휅휄뉅웱

 

2. 바이트 어레이 자료형(bytearray data type)

  • 바이트 자료형은 문자열처럼 변경이 불가능하지만 바이트 어레이 자료형은 리스트처럼 변경이 가능한 구조를 지원함
  • 변경이 가능하므로 리스트처럼 원소를 변경, 추가, 삭제할 수 있는 메서드를 지원함
  • 바이트 자료형처럼 바이트 기준으로 데이터를 관리함

2.1 bytes로 생성한 것을 bytearray로 변환 

  • bytes는 문자 하나하나가 모아서 문자열이 된거고
  • bytearray는 바이트 하나하나를 모아서 배열로 만든 것
  • 각 바이트들을 잘라서 동일한 내용을 바이트 어레이 형태로 만듬
b = b"strawberry"
ba = bytearray(b)

print(type(ba))
print(ba)

bs = bytearray("바이트어레이","utf-8")
print(bs)

<class 'bytearray'>
bytearray(b'strawberry')
bytearray(b'\xeb\xb0\x94\xec\x9d\xb4\xed\x8a\xb8\xec\x96\xb4\xeb\xa0\x88\xec\x9d\xb4') # 이건 bytes 가 아니고 바이트들이 모여서 어레이 형태를 이룬것

 

2.2 버퍼 처리하기 : bytearray

buffer = bytearray(20) # 바이트를 20개(1바이트=8비트, 160비트 사이즈의 메모리공간 미리 확보)
print(buffer)

bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') 

b = b"strawberry"
buffer[:len(b)] = b
print(buffer)

bytearray(b'strawberry\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')

 

#00은 아무데이터도 들어있지 않다 (아래 둘 중 하나의 경우일 것이다, 일반적으로는 2)

1. 한번도 사용되지않은 메모리 공간확보 하였다.

2. 바이트 어레이로 내용 만들었을때 내부적으로 초기화 하는 과정이 들어 있다.

 

2.3 bytes와 bytearray 메서드의 차이점

 
  • 바이트 어레이는 변경이 가능(수정이 가능)하므로 스페셜 메서드인 __ setitem __, __ delitem __을 지원한다.
  • 내부 원소를 변경 및 삭제할 수 있는 append, extend, remove, pop 메서드 등이 있으며 역정렬을 위한 reverse 메서드도 제공됨
  • bytes는 없고 bytearray만 있는것을 확인
import pprint

bs = set(dir(bytes))
bb = set(dir(bytearray))

pprint.pprint(bb - bs)

{'__alloc__', '__delitem__', '__iadd__', '__imul__', '__setitem__', 'append', 'clear', 'copy', 'extend', 'insert', 'pop', 'remove', 'reverse'}

 

buffer = bytearray(20)
print(buffer)

bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')

buffer.insert(0, 31) #0번인덱스에 31넣기
print(buffer)

bytearray(b'\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')

 

  • pop은 끄집어 내는데, 제일 뒤에있는것부터 꺼낸다.(자료 구조의 스택 형태)
  • 끝에 한개 빠지는것을 확인, pop은 remove대신에서 사용하기도 한다.
buffer.pop()
print(buffer)

bytearray(b'\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')

 

append는 제일 뒤에 추가하는것

buffer.append(31)
print(buffer)

bytearray(b'\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f')

 

버퍼는 바이트들이 배열을 이루고 있는것

인덱스 지정해서 뭔가를 집어넣지 못한다.

buffer[:3] = b'qwe'
print(buffer)

bytearray(b'qwe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f')

  • bytes와 bytearray 객체가 개별 요소를 처리할 때 정수(int) 타입을 기대하기 때문.
  • b'q'와 같은 바이트 리터럴은 실제로 바이트 문자열(bytes 객체)이며, 이 객체는 정수가 아니므로 오류가 발생한다.
buffer[0] = b'q'  # 이렇게는 안된다. (숫자값은 문제 없이 들어감)

TypeError: 'bytes' object cannot be interpreted as an integer

buffer.insert(0,b'q') # insert도 안된다.

TypeError: 'bytes' object cannot be interpreted as an integer

a = bytearray(b"abcd") # 바이트 어레이 만들어서 해도 역시 막히는 것을 알 수 있다.
a.insert(0,b"a")

TypeError: 'bytes' object cannot be interpreted as an integer

 

3. 튜플 자료형(tuple data type)

  • 튜플 자료형은 리스트 자료형과 동일하게 처리되지만 변경이 불가능함
  • 따라서 리스트와의 차이점은 내부 원소를 변경하거나 갱신하기 위한 메서드들이 존재하지 않는 것이다.
  • 튜플 자료형은 파이썬 내부적으로 변경이 되지 않으면서 관리되어야 할 기능에서 필요함
  • 튜플을 이용해서 데이터를 전달하는 방식으로 많이 사용됨 (이동시 데이터 바뀌지 않고 이동)

  • 튜플 자료형의 사용 사례
    • 함수의 매개변수에 가변적으로 들어오는 인자를 처리할 때
    • 특정 변수에 여러 데이터를 할당할 때
    • 함수의 반환값 여러 개를 하나로 묶어서 반환이 필요할 때 등

3.1 튜플 생성

  • 튜플 생성하는것은 기본적으로 리스트와 동일하다.(대괄호를 괄호로 바꾸는것)
  • 튜플 리터럴 및 생성자로 생성

리스트도 튜플로 생성자를 통해 생성 가능하다.

t = tuple([1,2,3,4])
print(t)

(1, 2, 3, 4)

 

문자열 사용(문자열도 하나의 리터럴임)

ts = tuple("원숭이")
print(ts)

('원', '숭', '이')

 

def func(x,y) :
    return x,y

t1 = func(10,6)
print(type(t1),t1)
a,b = func(10,6)
print(type(a),a)
print(type(b),b)

<class 'tuple'> (10, 6)

<class 'int'> 10

<class 'int'> 6

  • 튜플 내의 원소가 하나일 경우 주의사항
    • 단일 원소도 쉼표로 분리할 것
      • 스칼라 값인지 튜플인지 구분에 용이함
  • 파이썬에서는 (1) 이런식으로 쓰면 단일 데이터라고 인식함
  • (1,)는 튜플로 사용한다고 인식함
o = (1)
t = (1,)

print(type(o), o)
print(type(t), t)

<class 'int'> 1

<class 'tuple'> (1,)

 

3.2 튜플의 메서드

 

- 튜플은 파이썬에서 기본 자료형으로 사용함으로, 기본 예약어들이 많음

  • 메서드 확인
  • .startswith("__")는 __로 시작되는 경우를 의미함
t = dir(tuple)

for i in t :
    if not i.startswith("__") :
        print(i)

count

index

  • index 메서드 : 해당하는 인덱스를 가지고 오기
  • count 메서드 : 해당 값 카운팅
t = (1,2,3,2,3)

print(t.count(1))
print(t.count(2))
print(t.index(2))

print(t.index(2,3))

1

2

1

3

 

3.3 튜플 원소로 Mutable 자료형 처리 방법

 

원소가 리스트일 경우

 

t라는 변수가 가지는 id값

t = (1,3,[1,3])
print(id(t))

137170331165312

t[2][0] = 99
print(t)

(1, 3, [99, 3])

print(id(t))

137170331165312 # 아이피가 동일한것을 확인, 튜플에서 변경할 수 없다고 하지만 하나만 잘라내서 변경은 가능하다

 

 

4. 리스트 자료형(list data type)

  • 파이썬에서 가장 자주 사용되는 자료형
  • 변경가능한 Sequence 자료형이며 다양한 자료형을 내부의 원소로 수용할 수 있음
  • 리스트를 잘 활용하는게 매우 중요함

리스트 만들때 튜플 사용해서 만들어봄

l1 = list((1,2,3,))
print(type(l1),l1)

<class 'list'> [1, 2, 3]

 

리스트는 빈리스트를 만들 수 있다.(궁금해서 해봤는데 튜플도 가능)

l2 = []
print(l2)

[]

 

직접 데이터 넣어서도 만들 수 있음

l3 = [1,2,3]
print(l3)

[1, 2, 3]

 

4.2 리스트 복사 처리

 
  • 파이썬에서 복사가 되는 기준
    • 리스트 내에 변경이 가능한 원소가 들어올 경우, 단순히 복사하면 내부까지 전부 복사가 되지 않아 동일한 인스턴스를 공유한 채로 처리될 수 있다.(변경이 가능하므로 어떻게 변할지 모름으로)
    • 이런 점을 방지하기 위해서는 복사할 때 원소도 전부 다른 인스턴스로 변환이 되어야 다른 로직에서 리스트를 갱신할 때 공유된 리스트로 처리되는 것을 막을 수 있음
  • 2가지의 복사 기능
    • 얕은 복사(Shallow Copy): 새로운 객체를 만들지만 내부 원소는 기존 원소를 참조함
      • 리스트 자료형 내의 copy 메서드는 얕은 복사를 처리해서 새로운 리스트 인스턴스를 하나 만드는데 사용함
    • 깊은 복사(Deep Copy): 새로운 객체를 만들고 내부 원소들도 다른 원소로 만듦
 
  • 리스트로 선언된 변수의 별칭 사용
l = [1,2,3,4]

a = l

print(a is l)
print(a ==  l)

True

True

 

l 을 변경하나 a를 변경하나 동일하게 바뀌는 것을 확인함.

 

  • 리스트 내의 원소로 리스트를 가질 경우 copy 메소드 사용
l = [1,2,3,4]
lc = l.copy()
print(lc==l) 
print(lc is l) #  별도의 변수라는 것을 확인

True

False

l = [1,2,3,4]
ll = [l,l]
print(ll)

[[1, 2, 3, 4], [1, 2, 3, 4]]

lc = ll.copy()
print(lc)

[[1, 2, 3, 4], [1, 2, 3, 4]]

lc[0][0] = 77

print(l)
print(lc)

[77, 2, 3, 4]

[[77, 2, 3, 4], [77, 2, 3, 4]]

 

얕은 복사를 하니까 기존의 것을 이용해서 변형을함. (메모리 절약을 위해서 한것임)

외부에서 아무나 데이터 변형이 가능한 문제가 발생함

이를 해결하고자 깊은 복사를 이용한다.

 

  • 깊은 복사(deepcopy)를 하는 이유
    • 리스트 내의 copy 메서드는 리스트 자체만을 복사해서 새로운 사본을 만들고 리스트 내의 원소에 대해서는 사본을 만들지 않음
    • 리스트를 복사할 때 원본 리스트와 전혀 다른 리스트를 만들기 위해서는 리스트 내의 리스트 원소들도 다 다른 리스트가 만들어져야 함
    • 이를 처리하기 위하여 copy라는 모듈을 별도로 제공하고, 그 내부의 deepcopy 함수를 사용해서 복사하여 원본과는 전혀 다른 리스트를 생성함

deepcopy는 파이썬에서 표준 라이브러리로 포함하고는 있지만, 외부 라이브러리인 만큼 import copy를 이용해야한다.

import copy

l = [1,2,3,4]

ll = [l,l]
print(ll)

[[1, 2, 3, 4], [1, 2, 3, 4]]

lc = copy.deepcopy(ll)

print(lc)

[[1, 2, 3, 4], [1, 2, 3, 4]] 

lc[0][0] = 77

print(l)
print(lc)

[1, 2, 3, 4]

[[77, 2, 3, 4], [77, 2, 3, 4]] # 이 안에서는 공유되는 문제 발생

 

이를 통해 기존 데이터(l)은 변하지 않고 copy된 데이터만 수정되는것을 확인함

이번에는 l을 바로 집어넣지 않고 l을 복사해서 이용

전부 공유하지 않고 다 끊어서 사용

l = [1,2,3,4]
ll = [l.copy(),l.copy()]
print(ll)

lc = copy.deepcopy(ll)
print(lc)

lc[0][0] = 999
print(l)
print(lc)

[[1, 2, 3, 4], [1, 2, 3, 4]]
[[1, 2, 3, 4], [1, 2, 3, 4]]
[1, 2, 3, 4]
[[999, 2, 3, 4], [1, 2, 3, 4]]

 

4.3 리스트 자료형의 메서드

  • 리스트 주요 메서드
import pprint

for i in dir(list) :
    if not i.startswith("__") :
        print(i)

append
clear
copy
count
extend
index
insert
pop
remove
reverse
sort 

 

sort : 리스트 자체를 내부적으로 정렬

sort (reverse=Treu) : 역순으로 정렬

sorted() : 리스트의 정렬된 복사본을 반환

 

  • 리스트의 원소 추가 삭제하기
# 빈 리스트 생성
ll = []
print(ll)

[]

# 리스트의 끝에 원소 추가: 정수
ll.append(7)
print(ll)

[7]

# 리스트의 끝에 원소 추가: 리스트

ll.append([2,4])
print(ll)

[7, [2, 4]]

# 리스트에 값 삭제 : 삭제된 원소를 리턴값
a = ll.pop()
print(a)
print(ll)

[2, 4]

[7]

ll.append(2)
print(ll)

#특정 위치(인덱스)를 가지고 삭제
b = ll.pop(0)
print(b)
print(ll)

[7, 2]

7

[2]

  • 리스트 합치기: extend (리스트 확장 하기 위한것)
l8 = [1,2,3]
l10 = [4,5,6]

# l9에 다른 리스트 추가해서 합치기
l8.extend(l10)
print(l8)

l9 = [1,2,3]
print(l9 + l10)

[1, 2, 3, 4, 5, 6]

[1, 2, 3, 4, 5, 6]

 

  • 리스트 특정 위치에 삽입 및 전체 삭제
# 특정 위치에 삽입하기
l2 = [1,2,3,4]
l2.insert(0,5) #0번 인덱스에 5 집어넣기
print(l2)

[5, 1, 2, 3, 4]

l2.insert(0,7) #0번 인덱스에 7 집어넣기
print(l2)

[7, 5, 1, 2, 3, 4]

 

이런식으로 하면 0번 인덱스에 값을 넣고 나머지 값들은 한 칸씩 밀리는 것을 확인함.

 

값 삭제

remove는 값을 찾아서 삭제하는 것을 알 수 있다.( 앞에서 부터 지운다 )

# 특정 값으로 삭제
l2.remove(5)
print(l2)

[7, 1, 2, 3, 4]

l2.remove(7)
print(l2)

[1, 2, 3, 4]

 

전체 삭제

# 전체 삭제
l2.clear()
print(l2)

[ ]

  • 리스트 내의 동일원소를 확인하고 삭제하기

내부에서 같은값을 다 지우고 싶으면 반복문을 통해서 반복해서 지워야한다.

l4 = [1,2,3,4,5,2,2,2]
c = l4.count(2) # 동일한 원소 갯수 세기
print(c)

4

for i in range(c) :
    l4.remove(2)
print(l4)

[1, 3, 4, 5]

  • 리스트 원소들 정렬하기: sort, reverse
l4 = [1,2,3,4,5,2,2,2]

# 원소들 소팅 : 올림차수
l4.sort()
print(l4)

[1, 2, 2, 2, 2, 3, 4, 5]

# 원소들 소팅 : 역순으로 소팅 (단순히 뒤집어놓는것 정렬이 아님, 정렬 기능은 없음)
l4.reverse()
print(l4)

[5, 4, 3, 2, 2, 2, 2, 1]

# 소팅 기준을 주고 역순으로 소팅
l4.sort()
print(l4)

[1, 2, 2, 2, 2, 3, 4, 5]

l4.sort(reverse=True)
print(l4)

[5, 4, 3, 2, 2, 2, 2, 1]

 

4.4 리스트 내의 리스트 초기화 하기

  • 리스트로 * 연산자 비교하기
 
l = [4,5,6]
print(l)
l2 = l*2

print(l2)
l.extend(l)

[4, 5, 6]
[4, 5, 6, 4, 5, 6]

 

4.4.1 리스트 초기화 시 주의사항

  • 외부에 리스트 원소를 반복해서 처리하고 내부에 넣고 처리
row = [3] * 3
print(row)

[3, 3, 3]

li = []
for _ in range(3) :
    li.append(row)
print(li)

[[3, 3, 3], [3, 3, 3], [3, 3, 3]]

li[0][0] = 99
print(li)
print(row)

[[99, 3, 3], [99, 3, 3], [99, 3, 3]]

[99, 3, 3]

 

  • 리스트를 for문 안에서 초기화
li = []
for _ in range(3) :
    row = [3] * 3
    print(id(row))
    li.append(row)
print(li)

137170331240064

137170330408256

137170331247296

[[3, 3, 3], [3, 3, 3], [3, 3, 3]]

li[0][0] = 99

print(li)
print(id(row), row)

[[99, 3, 3], [3, 3, 3], [3, 3, 3]]

137170331247296 [3, 3, 3]

 

5.Sequence 자료형 형 변환

  • 파이썬은 별도의 형 변환 기능이 없음
  • Sequence 자료형, 숫자 자료형 등 형 변환은 새롭게 인스턴스를 만듦

5.1 클래스만 사용한 형 변환

l = [1,2,3,4]

t = tuple(l)
print(t)

s = str(l)
print(repr(s))

ls = list(s)
print(ls)

(1, 2, 3, 4)

'[1, 2, 3, 4]'

['[', '1', ',', ' ', '2', ',', ' ', '3', ',', ' ', '4', ']'] # 하나하나의 요소로 되어 변환됨

print(type(s))
print(type(ls))

<class 'str'>

<class 'list'>

  • 문자열 원소로 구성된 리스트나 튜플을 문자열로 변환
s = "yeon"

l = list(s)
print(l)

print("".join(l))

['y', 'e', 'o', 'n']

yeon

 

문자열이나 숫자로 구성된 리스트나 튜플을 문자열로 변환

l = [1,'h','e','l','l']

print(" ".join(l))

TypeError: sequence item 0: expected str instance, int found

 

1을 인티저가 아니라 str 시퀀스데이터 타입으로 변환해주어야함

str 생성자를 map으로 맵핑하라는 의미 - 시퀀스 데이터 형으로 다 바뀌므로 합성이 가능하다는 것이다.

l = [1,'h','e','l','l']

print("".join(map(str,l)))

1hell

 

6. 리스트 컴프리헨션(List Comprehension)

4.4.1 내용 리스트 컴프리헨션으로 변환한것

li = [ [3]*3 for _ in range(3)]
print(li)

li[0][0] = 99
print(li)

[[3, 3, 3], [3, 3, 3], [3, 3, 3]]

[[99, 3, 3], [3, 3, 3], [3, 3, 3]]

 

리스트 컴프리헨션 다른예시들

예시 1)

squares = [x**2 for x in range(1,6)]
print(squares)

[1, 4, 9, 16, 25]

 

예시 2)

even_squares = []
for i in range(1,11,2):
  even_squares.append(i**2)
print(even_squares)

[1, 9, 25, 49, 81]

  • 위 값을 리스트 컴프리헨션으로 변환
even_squares = [x**2 for x in range(1,11,2)]
print(even_squares)

[1, 9, 25, 49, 81]

 

예시3)

list_ = [3 * x for x in range(1,11)]
print(list_)

[3, 6, 9, 12, 15, 18, 21, 24, 27, 30]

 

예시4) if 구문 추가사용

list_ = [3 * x for x in range(1,11) if x % 3 != 0]
print(list_)

 

예시5) for문 두개 사용

list_ = [x * y for x in range(2, 5) for y in range(1,10)]
print(list_)

[2, 4, 6, 8, 10, 12, 14, 16, 18, 3, 6, 9, 12, 15, 18, 21, 24, 27, 4, 8, 12, 16, 20, 24, 28, 32, 36]

 

예시6) else 들어가는 경우 (for의 위치가 바뀜)

list_ = [3 * x if x % 3 != 0 else 1 for x in range(1, 11)]
print(list_)

[3, 6, 1, 12, 15, 1, 21, 24, 1, 30]

728x90

'PYTHON-BACK' 카테고리의 다른 글

#파이썬 기초 7일차_1  (1) 2024.07.05
#파이썬 기초 6일차_1  (0) 2024.07.04
#파이썬 기초 4일차_2  (1) 2024.07.02
#파이썬 기초 4일차_1  (0) 2024.07.02
#파이썬 기초 3일차  (1) 2024.07.01