
9. 제어문(반복문)
9-1. 반복문
9-1-6. zip() 함수
객체가 담고 있는 원소를 엮어서 튜플의 형태로 반환.
(자동으로 튜플의 형태로 반환되는것이 아니라, 코드에 소괄호를 넣어서 반환해주어야 함)
매개변수의 길이가 다를 때는 짧은 매개변수 기준으로 데이터가 엮이고, 나머지는 버려짐.
li1 = [10, 20, 30]
li2 = ['apple', 'banana', 'orange']
for i in range(len(li1)):
print((li1[i], li2[i]))
(10, 'apple')
(20, 'banana')
(30, 'orange')
zip() 비교용으로 작성한 코드. len(li1)과 len(li2)가 우연히 일치해서 적용이 가능한 코드로,
사용하기 좋은 코드는 아님.
위의 코드 대신 사용할 수 있는 코드가 아래의 zip()함수를 이용한 코드.
for l1, l2 in zip(li1, li2):
print((l1, l2))
(10, 'apple')
(20, 'banana')
(30, 'orange')
li1 = [10, 20, 30]
li2 = ['apple', 'banana', 'orange']
for li in zip(li1, li2):
print(li) # 'li'로 하나로 묶어서 반환할 수도 있음.
(10, 'apple')
(20, 'banana')
(30, 'orange')
for n, A, a in zip('12345', 'ABCDE', 'abcde'):
print((n, A, a))
# 문자를 각각 떼어내서 데이터를 만들 수도 있음.
('1', 'A', 'a')
('2', 'B', 'b')
('3', 'C', 'c')
('4', 'D', 'd')
('5', 'E', 'e')
for n, A, a in zip('12345', 'ABCDEF', 'abcde'):
print((n, A, a))
# 'F'가 있는 중간 데이터는 6개지만, 출력할 때 짧은 매개변수인 5개 기준으로 데이터가 엮이고
# 나머지 F는 버려짐.
('1', 'A', 'a')
('2', 'B', 'b')
('3', 'C', 'c')
('4', 'D', 'd')
('5', 'E', 'e')
9-1-7. 리스트(list)와 튜플(tuple)을 for문과 함께 사용하기
li1 = ['apple', 'banana', 'orange', 'melon'] # 리스트와 for문을 함께 사용하는 경우
for i in li1:
print(i, end=' ')
apple banana orange melon
tu1 = ('apple', 'banana', 'orange', 'melon') # 튜플과 for문을 함께 사용하는 경우
for i in tu1:
print(i, end=' ')
apple banana orange melon
아래 score 리스트에 저장된 점수가 60점 이상인 학생이 몇 명인지 알아보는 프로그램을 작성해보자.
score = [90, 30, 50, 60, 80, 70, 100, 40, 20, 10]
score = [90, 30, 50, 60, 80, 70, 100, 40, 20, 10] # 이터러블한 객체이다.
count = 0 # count라는 변수를 생성한다.
for i in score:
if i >= 60:
count += 1 # i값이 60 이상인 경우 count값이 1씩 증가한다.
print(f'60점 이상인 학생인 수는 {count}명 입니다.')
60점 이상인 학생인 수는 5명 입니다.
9-2. 다중 반복문
반복문이 2개 이상 겹쳐져 있는 형태
for i in range(1,4): # 증가값이 생략되어있음. 기본 증가값 1이고 1부터 3까지 출력.
print(f'😎 i: {i}')
for j in range(1,4):
print(f' 😍 j: {j}') # i가 돌 때마다 j가 매번 도는 결과를 출력
😎 i: 1
😍 j: 1
😍 j: 2
😍 j: 3
😎 i: 2
😍 j: 1
😍 j: 2
😍 j: 3
😎 i: 3
😍 j: 1
😍 j: 2
😍 j: 3
'🎃'를 이용하여 아래와 같은 도형을 만들어보자.
'''
🎃 🎃 🎃 🎃 🎃
🎃 🎃 🎃 🎃 🎃
🎃 🎃 🎃 🎃 🎃
🎃 🎃 🎃 🎃 🎃
🎃 🎃 🎃 🎃 🎃
'''
for i in range(5): # 시작값 0, 증가값 1이 생략이 되어있음. 0~4까지 5바퀴를 돌릴 예정.
for j in range(5):
print('🎃', end=' ')
print() # 엔터키의 역할로 줄을 나누어 줌
# i가 세로줄의 수를 담당, j가 가로줄의 수를 담당
🎃 🎃 🎃 🎃 🎃
🎃 🎃 🎃 🎃 🎃
🎃 🎃 🎃 🎃 🎃
🎃 🎃 🎃 🎃 🎃
🎃 🎃 🎃 🎃 🎃
'🎃'를 이용하여 아래와 같은 도형을 만들어보자.
🎃 🎃 🎃 🎃 🎃
🎃 🎃 🎃 🎃
🎃 🎃 🎃
🎃 🎃
🎃
for i in range(5):
for j in range(i, 5): # i값이 0, 1, 2, 3, 4로 차례대로 늘어남.
print('🎃', end=' ')
print()
🎃 🎃 🎃 🎃 🎃
🎃 🎃 🎃 🎃
🎃 🎃 🎃
🎃 🎃
🎃
'🎃'를 이용하여 아래와 같은 도형을 만들어보자.
🎃
🎃 🎃
🎃 🎃 🎃
🎃 🎃 🎃 🎃
🎃 🎃 🎃 🎃 🎃
for i in range(5):
for j in range(i+1): # 종료값이 직전값인 i로 나와야 하므로 i+1을 입력
print('🎃', end=' ')
print()
🎃
🎃 🎃
🎃 🎃 🎃
🎃 🎃 🎃 🎃
🎃 🎃 🎃 🎃 🎃
2단부터 9단까지 구구단을 출력하는 프로그램을 작성
for i in range(2,10): # '단'을 돌려줄 숫자
print(f'{i}단')
for j in range(1,10):
print(f'{i} * {j} = {i*j}')
print() # '단'이 넘어갈때마다 줄나눔을 해주는 역할
2단부터 9단까지 구구단을 출력하는 프로그램을 while문을 이용해서 작성해보자.
i = 2
j = 1
while i <= 9 :
print(f'{i}단')
while j <= 9 :
print(f'{i} * {j} = {i*j}')
j += 1
i += 1
j = 1
# j가 9까지 돌고 나서, i값이 1 증가할 때, j값을 다시 1로 초기화를 시켜줘야 함.
# 이 줄이 없으면, 2단만 정상적으로 나오고 3단부터는 출력이 되지 않음.
print() # while문은 저절로 초기화가 되지 않기 때문에 직접 초기화를 시켜주어야 함.
아래 score 리스트의 요소를 모두 출력하는 프로그램을 작성해보자.
score = [[80,90,50],[40,70,30],[90,50,100]]
for i in range(3): # i를 3바퀴를 돌림
for j in range(3): # j를 3바퀴를 돌림
print(score[i][j], end=' ')
80 90 50 40 70 30 90 50 100
데이터는 언제든지 바뀔 수 있기 때문에 range(3)과 같이 상수로 고정된 코드는 좋은 코드가 아님.
추후에 수정해야 할 가능성이 생김.
▼
다른 코드
for i in score:
for j in i:
print(j, end=' ')
80 90 50 40 70 30 90 50 100
# 위의 코드보다 이 코드를 사용하는 것이 더 편하다.
# end=' '는 세로로 출력이 아니라, 가로로 출력하고 싶을 때 사용
9-3. Comprehension
이터러블한 오브젝트를 '생성'하기 위한 방법 중 하나로 파이썬에서 사용할 수 있는 유용한 기능.
n = range(0, 10, 1) # 일반적인 이터러블한 객체의 생성.
result = [0 for i in range(n)]
# 0부터 9까지 1씩 증가되는 10개의 범위를 생성하고, i에 0을 대입하여 리스트를 생성.
print(result) # 이터러블한 객체를 생성.
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
result = [i for i in range(n)]
print(result)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
result = [n*n for n in arr]
print(result) # n개의 범위에서 arr의 숫자가 n*n으로 계산이 되어 리스트로 생성이 됨.
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
arr = ['apple', 'banana', 'orange', 'melon']
result = [len(string) for string in arr] # 리스트 안의 문자열의 문자 수를 세어서 리스트로 생성이 됨.
print(result)
[5, 6, 6, 5]
result = [n for n in range(10) if n%2==0] # 조건문 if문을 삽입할 수 있음.
print(result)
[0, 2, 4, 6, 8]
0부터 100까지의 숫자 중에서 3의 배수이며, 홀수인 숫자만 리스트에 저장하기
result = [n for n in range(101) if n%3==0 and n%2==1]
print(result)
[3, 9, 15, 21, 27, 33, 39, 45, 51, 57, 63, 69, 75, 81, 87, 93, 99]
양수는 리스트에 저장하고, 음수는 0으로 변환해서 저장하기
arr = [-1, 0 ,-4, 24, 5, -10, 2]
result = [n if n>0 else 0 for n in arr] # n이 있는 앞부분에 조건문 if를 삽입할 수 있음.
print(result)
[0, 0, 0, 24, 5, 0, 2]
arr = []
for i in range(1, 4): # 1 2 3
for j in range(1, 3): # 1 2
arr.append(i*j)
print(arr) # 1*1, 1*2, 2*1, 2*2, 3*1, 3*2로 출력됨
[1, 2, 2, 4, 3, 6]
(다른 코드)
arr = [i*j for i in range(1,4) for j in range(1,3)]
print(arr)
[1, 2, 2, 4, 3, 6]
result = [[0 for i in range(2)] for j in range(3)] # 이차원 리스트를 생성할 수 있음
print(result) # i는 0이 2개가 있는 리스트, j는 i 리스트 3개를 가진 리스트
[[0, 0], [0, 0], [0, 0]]
10. 딕셔너리(dictionary)
10-1. 딕셔너리(dictionary)
대응관계를 나타내는 자료형으로, key와 value라는 것을 한 쌍으로 갖는 형태.
예를 들어, 사물함의 각각의 key라는 열쇠를 이용해서 저장된 물건인 value를 꺼낼 수 있음.
하나의 딕셔너리의 key는 중복될 수 없지만, value는 중복이 될 수 있음.
10-1-1. 딕셔너리 만들기
변수 = {key1:value1, key2:value2 ...} |
dic1 = {1:'김사과', 2:'반하나', 3:'오렌지', 4:'이메론'} # 하나의 딕셔너리를 생성한다. 중괄호를 사용해서 만든다.
print(dic1)
print(type(dic1)) # 딕셔너리의 타입은 'dict'(딕셔너리)이다.
{1: '김사과', 2: '반하나', 3: '오렌지', 4: '이메론'}
<class 'dict'>
10-1-2. key를 통해 value를 찾기
dic2 = {1:'김사과', 2:'반하나', 3:'오렌지', 4:'이메론'}
print(dic2[1]) # 인덱스와 다르다.
print(dic2[2])
print(dic2[3])
print(dic2[4])
김사과
반하나
오렌지
이메론
dic3 = {'no':1, 'userid':'apple', 'name':'김사과', 'hp':'010-1111-1111'} # key값이 문자열인 경우도 가능.
print(dic3['no'])
print(dic3['userid'])
1
apple
10-1-3. 데이터의 추가 및 삭제
dic4 = {1:'apple'}
dic4[100] = 'orange' # key가 100이고 value가 orange인 값을 추가
print(dic4)
{1: 'apple', 100: 'orange'}
del dic4[1] # dic4의 key가 1인 값을 삭제
print(dic4)
{100: 'orange'}
10-1-4. 딕셔너리 함수
keys() : key 리스트를 반환
dic5 = {'no':1, 'userid':'apple', 'name':'김사과', 'hp':'010-1111-1111'}
print(dic5.keys())
dict_keys(['no', 'userid', 'name', 'hp'])
values() : value 리스트를 반환
print(dic5.values())
dict_values([1, 'apple', '김사과', '010-1111-1111'])
items() : key와 value를 한 쌍으로 묶는 튜플을 반환
print(dic5.items())
dict_items([('no', 1), ('userid', 'apple'), ('name', '김사과'), ('hp', '010-1111-1111')])
get() : key를 이용해서 value를 반환.
print(dic5.get('userid'))
print(dic5.get('age'))
# 딕셔너리에 해당되는 키가 없다면 value를 반환요청했을 때 None이 출력됨. '가리키는 데이터가 없다'라는 의미.
print(dic5.get('age','나이를 알 수 없음')) # 뒤에 '나이를 알 수 없음'은 None을 대체하여 출력하는 것
apple
None
나이를 알 수 없음
in : key가 딕셔너리 안에 있는지 확인할 수 있음. (키워드로, 함수가 아님.)
print('name' in dic5) # 실제로 있는 key라면 True가 출력
print('age' in dic5) # 없는 key라면 False가 출력
True
False
10-1-5. 반복문을 이용한 딕셔너리 활용
dic5 = {'no':1, 'userid':'apple', 'name':'김사과', 'hp':'010-1111-1111'}
for i in dic5:
print(i, end=' ') # key만 복사하여 가져올 수 있음.
no userid name hp
for i in dic5.keys():
print(i, end=' ') # key만 복사하여 가져올 수 있음.
no userid name hp
for i in dic5.values():
print(i, end=' ') # value만 복사하여 가져올 수 있음.
1 apple 김사과 010-1111-1111
for i in dic5:
print(dic5[i], end=' ') # value만 복사하여 가져올 수 있음. 가장 많이 사용하게 될 방식.
1 apple 김사과 010-1111-1111
for i in dic5:
print(dic5.get(i), end=' ') # value만 복사하여 가져올 수 있음.
1 apple 김사과 010-1111-1111
각 key를 순회하면서, 각 key에 해당하는 value에 apple이 있는지 확인해보기
dic5 = {'no':1, 'userid':'apple', 'name':'김사과', 'hp':'010-1111-1111'}
for i in dic5:
if dic5[i] == 'apple':
print('찾았습니다')
else:
print('찾지못했음')
찾지못했음
찾았습니다
찾지못했음
찾지못했음
11. 세트(set)
11-1. 세트(set)
순서가 없어서 어떤 값이 먼저 나올 지 알 수 없고, 중복되는 데이터를 허용하지 않음.
딕셔너리와 비슷하게 중괄호를 사용해서 선언하지만, key는 존재하지 않고 value만 존재하는 자료구조.
11-1-1. set 만들기
s1 = { }
print(s1)
print(type(s1)) # 처음 빈칸만 있을때는 key, value값 중 무엇이 저장될지를 모르기 때문에 'dict' 타입으로 출력.
{ }
<class 'dict'>
s1 = {1, 3, 5, 7}
print(s1)
print(type(s1)) # 중괄호 안에 값이 들어있다면, 'set' 타입으로 출력.
{1, 3, 5, 7}
<class 'set'>
li1 = [1, 3, 5, 7] # 리스트를 세트로 바꿀 수 있음.
s2 = set(li1)
print(s2)
{1, 3, 5, 7}
s3 = {1, 3, 5, 7, 9, 1}
print(s3) # 세트 안의 중복되는 '1'이 사라지게 됨. 중복되는 데이터를 허용하지 않기때문.
{1, 3, 5, 7, 9}
li2 = [1, 3, 5, 3, 7, 9, 1]
print(li2) # 리스트는 중복된 값을 허용
s4 = set(li2)
print(s4) # 리스트에서 중복된 데이터가 모두 사라지고 출력. 중복되지 않는 값만 뽑아내고 싶을 때 활용 가능.
[1, 3, 5, 3, 7, 9, 1]
{1, 3, 5, 7, 9}
print(3 in s4) # s4에 3이 있다. True
print(8 in s4) # s4에 8이 들어있다. False
print(8 not in s4) # s4에 8이 들어있지 않다. True
True
False
True
11-1-2. set 함수
add() : set에 단일 데이터를 추가
s1 = {100, 200}
s1.add(150) # in-place연산에 의해 데이터가 바로 적용이 됨
print(s1)
s1.add(50)
print(s1) # 추가되어 출력된 순서는 불명확함.
{200, 100, 150}
{200, 50, 100, 150}
update() : set에 여러 데이터를 한번에 추가.
s2 = {10, 20, 30}
s2.update([40, 50, 60, 20]) # 20은 중복이 되어서 하나만 출력됨.
print(s2)
{40, 10, 50, 20, 60, 30}
remove() : set의 데이터를 제거.
s2.remove(50)
print(s2)
s2.remove(70)
print(s2) # 제거할 데이터가 없다면 에러가 발생.
discard() : set의 데이터를 제거.
s2 = {10, 20, 30}
s2.discard(50)
print(s2) # 제거할 데이터가 없어도 에러가 발생하지 않고 그냥 넘어가버림.(remove()와의 차이점)
{10, 20, 30}
copy() : set을 복사.
s3 = {10, 20, 30}
s4 = s3.copy()
print(s3)
print(s4)
print(id(s3)) # 값은 같지만, id() 함수를 사용했을 때 저장된 메모리주소는 서로 다름.
print(id(s4))
{10, 20, 30}
{10, 20, 30}
140098672137152
140098672137600
id() : 저장된 메모리주소를 10진수로 표현.
li1 = [1, 2, 3, 4]
li2 = li1 # li1의 메모리 주소가 li2로 복사된 상황.
print(id(li1))
print(id(li2)) # 같은 주소를 가리키고 있음.
140098466682432
140098466682432
11-1-3. set의 연산자
s1 = {10, 20, 30, 40, 50}
s2 = {30, 40, 50, 60, 70}
# 합집합
result = s1 | s2
print(result)
{70, 40, 10, 50, 20, 60, 30}
result = s1.union(s2) # union()이라는 메서드를 사용할 때.
print(result)
{70, 40, 10, 50, 20, 60, 30}
# 교집합
result = s1 & s2
print(result)
{40, 50, 30}
result = s1.intersection(s2) # intersection()이라는 메서드를 사용할 때.
print(result)
{40, 50, 30}
# 차집합
result = s1 - s2
print(result)
{10, 20}
result = s1.difference(s2) # difference()라는 메서드를 사용할 때.
print(result)
{10, 20}
# 대칭 차집합 (합집합 - 교집합)
result = s1 ^ s2
print(result)
{20, 70, 10, 60}
result = s1.symmetric_difference(s2) # symmetric_difference()이라는 메서드를 사용할 때.
print(result)
{20, 70, 10, 60}
11-2. set와 zip()함수
string = 'apple'
li = [1, 2, 3, 4, 5]
tu = ('김사과', '반하나', '오렌지', '이메론', '채애리')
print(list(zip(string, li, tu))) # 튜플로 하나씩 데이터를 묶은 것들을 리스트로 묶음

print(set(zip(string, li, tu)))
# 튜플로 하나씩 데이터를 묶은 것들을 세트로 묶음. 세트는 항상 불명확한 순서로 출력.

print(dict(zip(li, tu)))
# 딕셔너리는 그대로 출력 시 에러가 발생. string을 빼고 출력하면 정상적으로 출력.

print(dict(zip(string, tu)))
# key는 중복이 되지 않기 때문에 'p'를 중복하여 key를 가질 수 없음.
# set가 항상 불명확한 순서로 출력되는 이유는 linkedlist에 따라 랜덤의 개념이 아니다.

12. 사용자 정의 함수
12-1. 함수
변수 x, y에 대해 x값이 정해지면 그에 따라 y값을 결정하는 것.(수학적인 의미)
반복적으로 사용되는 가치있는 부분을 묶어서 하나의 집합으로 만듦. (프로그래밍의 의미)
코드를 재활용하기 위한 목적.
12-1-1. 이름만 있는 함수 (편의상의 제목)
def 함수명(): 함수가 호출되면 실행할 문장 호출 시 : 함수명 |
def func1():
print('처음으로 만드는 함수')
func1()
처음으로 만드는 함수
for i in range(5):
func1() # def를 통해 만든 함수도 반복이 가능함.
처음으로 만드는 함수
처음으로 만드는 함수
처음으로 만드는 함수
처음으로 만드는 함수
처음으로 만드는 함수
1-2. 매개변수가 있는 함수
def 함수명(변수1, 변수2, ...): 함수가 호출되면 실행할 문장 호출 시 : 함수명(값1, 값2, ...) |
def func2(num):
print(f'입력받은 숫자: {num}')
func2(10)
입력받은 숫자: 10
def func3(start, end):
sum = 0
for i in range(start, end+1):
sum += i
print(f'{start}부터 {end}까지의 합: {sum}')
func3(1,10)
1부터 10까지의 합: 55