반복과 리스트¶
섭씨 화씨 테이블 작성¶
다음과 같은 섭씨와 화씨에 대한 테이블을 어떻게 작성할까요?
-20 -4.0
-15 5.0
-10 14.0
-5 23.0
0 32.0
5 41.0
10 50.0
15 59.0
20 68.0
25 77.0
30 86.0
35 95.0
40 104.0
한 줄에 대한 섭씨/화씨는 다음과 같이 계산합니다.
C = -20
F = 9.0 / 5 * C + 32
print(C, F)
따라서 여러 개를 복사/붙여넣기를 하여 변경할 수 있습니다.
C = -20; F = 9.0 / 5 * C + 32; print(C, F)
C = -15; F = 9.0 / 5 * C + 32; print(C, F)
# ...
C = 35; F = 9.0 / 5 * C + 32; print(C, F)
C = 40; F = 9.0 / 5 * C + 32; print(C, F)
매우 지루하고 오류가 나기 쉬운 작업입니다.
컴퓨터는 이러한 반복 작업을 매우 빨리 실행합니다.
컴퓨터 언어는 이러한 작업을 위한 반복문(loop)이 있습니다.
while
문¶
while
문은 조건이 참인 동안 주어진 구역을 계속 반복 실행합니다.
while condition:
<statement 1>
<statement 2>
...
<first statement after loop>
모든 문장은 들여쓰기를 해야합니다.
반복 구역은 들여쓰기가 해제되면 끝납니다.
while
문장을 이용한 테이블¶
In [1]: print(30 * '-') # 테이블 시작
...: C = -20 # 시작값 C
...: dC = 5 # 증가량 C
...: while C <= 40: # 조건을 갖는 while 머리 부분
...: F = (9.0 / 5) * C + 32 # while 구역 1번째 문장
...: print('{:10.2f} {:10.2f}'.format(C, F)) # while 구역 2번째 문장
...: C = C + dC # while 구역 3번째 문장
...: print(30 * '-') # 테이블 끝
...:
------------------------------
-20.00 -4.00
-15.00 5.00
-10.00 14.00
-5.00 23.00
0.00 32.00
5.00 41.00
10.00 50.00
15.00 59.00
20.00 68.00
25.00 77.00
30.00 86.00
35.00 95.00
40.00 104.00
------------------------------
while
문 예제 분석¶
C = -20
dC = 5
while C <= 40:
F = (9.0/5)*C + 32
print('{:10.2f} {:10.2f}'.format(C, F))
C = C + dC
손으로 한줄 한줄 분석해 봅니다.
C
는 -20 이므로 \(-20 \leq 40\) 이 참입니다. 따라서 반복 구역을 실행합니다.F
를 계산하고 출력합니다.C
를 -15로 업데이트합니다다시
while
줄로 돌아가서 \(C\leq 40\) 이 참인지를 판단한 후 반복 구역을 실행합니다.이러한 과정을
C
가 45가 되기 전까지 반복합니다.\(45\leq 40\)가 False이기 때문에 반복 구역을 실행하지 않고 반복 구역 다음 문장을 실행합니다.
bool¶
참 또는 거짓을 갖는 식을 논리식(boolean expression)이라고 합니다. 예를 들면
C == 40 # C는 40과 같다. 등호 2개를 사용합니다. 등호 1개는 할당문입니다.
C != 40 # 같지 않다.
C >= 40 # 크거나 같다.
C > 40 # 크다.
C < 40 # 작다.
다음과 같이 같지 않다의 결과를 확인할 수 있습니다.
In [2]: C = 41
...: C != 40
...:
Out[2]: True
작다.
In [3]: C < 40
Out[3]: False
같다.
In [4]: C == 41
Out[4]: True
논리식 결합¶
여러 개의 논리식을 and
또는 or
또는 not
등을 이용해서 결합할 수 있습니다.
while condition1 and condition2:
...
while condition1 or condition2:
...
A |
B |
A |
A |
|
---|---|---|---|---|
True |
True |
True |
True |
False |
True |
False |
True |
False |
False |
False |
True |
True |
False |
True |
False |
False |
False |
False |
True |
In [5]: x = 0; y = 1.2
...: x >= 0 and y < 1
...:
Out[5]: False
In [6]: x >= 0 or y < 1
Out[6]: True
In [7]: x > 0 or y > 1
Out[7]: True
In [8]: x > 0 or not y > 1
Out[8]: False
In [9]: -1 < x <= 0 # -1 < x and x <= 0
Out[9]: True
In [10]: not (x > 0 or y > 0)
Out[10]: False
리스트(list)¶
이제까지는 하나의 변수는 하나의 숫자 또는 문자열을 담고 있었습니다. 그러나 때때로 하나의 변수에 여러 개의 숫자들을 담고 있으면 편리할 때가 많습니다.
예를 들면 하나의 변수에 하나의 숫자를 대입할 경우는 다음과 같이 많은 수의 변수들을 도입해야합니다. 매우 지루하고 불편한 작업입니다.
C1 = -20
C2 = -15
C3 = -10
# ...
C13 = 40
그렇지만 다음과 같이 하나의 변수에 여러 개의 숫자를 담을 수 있으면 다루기가 훨씬 편리해집니다. 다음은 파이썬 리스트를 이용해서 하나의 변수 C
에 숫자들을 담는 예입니다.
C = [-20, -15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40]
리스트 생성 및 인덱스¶
리스트는 대괄호 사이에 원하는 원소들을 쉼표로 구분해서 만듭니다. 리스트의 원소는 어떤 파이썬 객체도 가능합니다.
다음 L1
은 파이썬 리스트입니다.
In [11]: L1 = [-91, 'a string', 7.2, 0]
리스트의 원소에 접근하기 위해서는 인덱스를 사용합니다. L1[3]
(인덱스=3).
인덱스는 리스트의 위치를 나타내는 정수로 0
이 첫번째 원소를 1
이 두번째 원소 2
가 3번째 원소 … 마지막 원소는 len(L1)-1
입니다. len()
는 리스트 원소의 갯수를 반환합니다.
In [12]: mylist = [4, 6, -3.5]
....: print(mylist[0])
....:
4
In [13]: print(mylist[1])
6
In [14]: print(mylist[2])
-3.5
리스트의 원소갯수
In [15]: len(mylist) # length of list
Out[15]: 3
리스트 추가, 확장, 삽입, 삭제¶
리스트의 append()
함수를 이용하여 마지막에 원소를 추가합니다.
In [16]: C = [-10, -5, 0, 5, 10, 15, 20, 25, 30]
....: C.append(35) # 35를 맨 나중에 추가
....: C
....:
Out[16]: [-10, -5, 0, 5, 10, 15, 20, 25, 30, 35]
더하기 기호 +
는 새로운 리스트를 만들어 반환합니다.
In [17]: C = C + [40, 45] # extend C at the end
....: C
....:
Out[17]: [-10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
insert()
함수를 이용하여 원하는 위치에 삽입합니다.
다음은 0번째에 -15
를 삽입합니다.
In [18]: C.insert(0, -15) # insert -15 as index 0
....: C
....:
Out[18]: [-15, -10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
del
함수를 이용하여 원소를 제거할 수 있습니다. 3번째 원소를 제거합니다.
In [19]: del C[2] # delete 3rd element
....: C
....:
Out[19]: [-15, -10, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
3번째 원소가 삭제되면 뒤에 있는 4번째 원소가 3번째로 됩니다. 뒤에 있는 원소들이 하나씩 앞으로 당겨집니다.
다시 3번째 원소를 제거합니다.
In [20]: del C[2] # delete what is now 3rd element
....: C
....:
Out[20]: [-15, -10, 5, 10, 15, 20, 25, 30, 35, 40, 45]
원소의 갯수가 2개 줄은 것을 확인할 수 있습니다.
In [21]: len(C) # length of list
Out[21]: 11
리스트 원소 찾기, 음수 인덱스¶
index()
함수는 원소가 속해있는 인덱스를 반환합니다.
In [22]: C.index(10) # index of the first element with value 10
Out[22]: 3
in
연산자를 이용해서 리스트의 원소인지를 판단할 수 있습니다.
다음은 10
이라는 숫자가 C
에 속해있는지를 판단합니다.
In [23]: 10 in C # is 10 an element in C?
Out[23]: True
음의 정수 인덱스는 끝에서부터 찾습니다.
In [24]: C[-1] # the last list element
Out[24]: 45
끝에서 2번째
In [25]: C[-2] # the next last list element
Out[25]: 40
슬라이스(slice)¶
콜론 :
을 이용해서 연속적인 인덱스를 대신할 수 있습니다. 이러한 것을 슬라이스라고 합니다.
슬라이스 형식은 다음과 같습니다.
리스트[시작:끝]
끝
은 포함되지 않습니다.
다음은 인덱스 1부터 3까지의 연속적인 원소들을 리스트로 반환합니다.
In [26]: x = [1, 2, 3, 4, 5]
....: x[1:4]
....:
Out[26]: [2, 3, 4]
음수 인덱스를 사용해도 됩니다.
In [27]: x[2:-1]
Out[27]: [3, 4]
시작
인덱스를 생략하면 처음 원소부터 시작합니다.
In [28]: x[:4]
Out[28]: [1, 2, 3, 4]
끝
인덱스를 생략하면 마지막 성분까지 포함됩니다.
In [29]: x[2:]
Out[29]: [3, 4, 5]
리스트 풀기(unpacking)¶
In [30]: somelist = ['book.tex', 'book.log', 'book.pdf']
....: texfile, logfile, pdf = somelist # 리스트 성분을 직접 각 변수에 대입
....: texfile
....:
Out[30]: 'book.tex'
In [31]: logfile
Out[31]: 'book.log'
In [32]: pdf
Out[32]: 'book.pdf'
for 문¶
리스트의 각 성분을 순회하는데 for
문을 사용할 수 있습니다.
for
문의 사용법은 다음과 같습니다.
for var in iterable:
...
예를 들면
In [33]: degrees = [0, 10, 20, 40, 100]
....: for C in degrees:
....: print('섭씨 : {} 도'.format(C))
....: F = 9 / 5. * C + 32
....: print('화씨 : {}도'.format(F))
....: print('리스트의 크기는 {} 입니다.'.format(len(degrees)))
....:
섭씨 : 0 도
화씨 : 32.0도
섭씨 : 10 도
화씨 : 50.0도
섭씨 : 20 도
화씨 : 68.0도
섭씨 : 40 도
화씨 : 104.0도
섭씨 : 100 도
화씨 : 212.0도
리스트의 크기는 5 입니다.
if
, while
문과 마찬가지로 for
문의 반복 문장들은 같은 양만큼 들여쓰기가 되어야 합니다.
위 for
문을 분석하면 다음과 같습니다.
C
에는0
이 할당됩니다.print('섭씨 : {} 도'.format(C))
문이 실행되어섭씨 : 0도
가 출력됩니다.F = 9 / 5. * C + 32
문장이 계산이 되어F
에 계산된 값 32.0이 할당됩니다.print('화씨 : {}도'.format(F))
문이 실행되어화씨 : 32.0도
가 출력됩니다.다시
for
문 시작으로 돌아가서C
에는10
이 할당됩니다.C = 100
이 될때까지 반복하고for
문을 끝냅니다.다음 문장
print('리스트의 크기는 {} 입니다.'.format(len(degrees)))
을 실행합니다.
리스트 활용¶
수식의 합 계산¶
다음과 같은 합 \(S\)을 계산하는 것을 생각해봅니다.
for
문을 이용하여 계산해봅니다.
In [34]: N = 14
....: S = 0
....: for i in range(1, N + 1):
....: S += i ** 2
....: print('sum = ', S)
....:
sum = 1015
잘 사용하지는 않지만 while
문을 이용하여 계산해봅니다.
In [35]: N = 14
....: S = 0
....: i = 0
....: while i <= N:
....: S += i ** 2
....: i += 1 # 반복을 끝내기 위한 문장
....: print('sum = ', S)
....:
sum = 1015
여기서 주의해야 할 것은 i
를 초기화해야 하며 while
문에서 반드시 반복을 끝나는 문장을 넣어 주어야 한다는 것입니다.
반복문에서 만들어진 결과값들을 리스트로 저장할 수 있습니다.
In [36]: Cdegrees = [-20, -15, -10, -5, 0, 5, 10,
....: 15, 20, 25, 30, 35, 40]
....: Fdegrees = [] # 빈 리스트
....: for C in Cdegrees:
....: F = (9.0 / 5) * C + 32
....: Fdegrees.append(F) # Fdegrees에 추가
....: print(Fdegrees)
....:
[-4.0, 5.0, 14.0, 23.0, 32.0, 41.0, 50.0, 59.0, 68.0, 77.0, 86.0, 95.0, 104.0]
직접하기¶
다음 \(\sin(x)\)의 테일러 다항식을 이용하여 \(\sin(\pi/6)\)의 근사값을 10항까지 계산하세요.
math.factorial()
함수와 반복문을 이용하세요.\[\sin(x) \approx x - \frac{1}{3!} x^3 + \frac{1}{5!} x^5 \cdots\]
range
함수¶
일반적으로 for
문을 사용할 때는 리스트의 값들에 대해서 순회하면서 계산합니다.
for element in somelist:
# element에 대한 계산
range()
함수를 이용해서 인덱스로 리스트를 접근할 수 있습니다.
for i in range(0, len(somelist), 1):
element = somelist[i]
# process element or somelist[i] directly
range(start, stop, inc)
는 start
에서 시작해서 start + inc
씩 증가(또는 감소) stop
까지 증가(또는 감소)합니다. stop
은 포함되지 않습니다.
range(3) # range(0, 3, 1)과 같습니다.
In [37]: range(2, 8, 3)
Out[37]: range(2, 8, 3)
리스트 원소 변경¶
리스트 v = [-1, 1, 10]
의 원소에 각각 2씩 더하려고 합니다.
다음 코드가 적당할까요?
v = [-1, 1, 10]
for e in v:
e = e + 2
print(v)
리스트의 원소를 변경하려면 리스트의 인덱스로 접근해야 합니다.
for i in range(len(v)):
v[i] = v[i] + 2
리스트 축약(list comprehension)¶
리스트를 생성하는 편리한 방법이 리스트 축약입니다.
[표현식 for 변수 in 리스트]
일반적으로 다음과 같이 두 개의 리스트를 계산할 수 있습니다.
n = 16
Cdegrees = [] # 빈 리스트
Fdegrees = [] # 빈 리스트
for i in range(n):
Cdegrees.append(-5 + i * 0.5)
Fdegrees.append((9.0 / 5) * Cdegrees[i] + 32)
print(Cdegrees)
print(Fdegress)
이것을 리스트축약을 이용하면 다음과 같이 한 줄로 만들 수 있습니다.
In [38]: n = 16
....: Cdegrees = [-5 + i*0.5 for i in range(n)]
....: Fdegrees = [(9.0/5)*C + 32 for C in Cdegrees]
....: print(Cdegrees)
....: print(Fdegrees)
....:
[-5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5]
[23.0, 23.9, 24.8, 25.7, 26.6, 27.5, 28.4, 29.3, 30.2, 31.1, 32.0, 32.9, 33.8, 34.7, 35.6, 36.5]
동시에 여러 리스트 순회¶
동시에 여러 리스트를 순회하는 방법으로 다음과 같은 방법이 있습니다.
for i in range(len(Cdegrees)):
print(Cdegrees[i], Fdegrees[i])
하지만 좀더 간단한 방법은 zip()
함수를 이용하여 두 개의 리스트를 동시에 순회할 수 있습니다.
In [39]: for C, F in zip(Cdegrees, Fdegrees):
....: print(C, F)
....:
-5.0 23.0
-4.5 23.9
-4.0 24.8
-3.5 25.7
-3.0 26.6
-2.5 27.5
-2.0 28.4
-1.5 29.3
-1.0 30.2
-0.5 31.1
0.0 32.0
0.5 32.9
1.0 33.8
1.5 34.7
2.0 35.6
2.5 36.5
3개의 리스트를 동시에 순회할 수도 있습니다.
In [40]: l1 = [3, 6, 1]; l2 = [1.5, 1, 0]; l3 = [9.1, 3, 2]
....: for e1, e2, e3 in zip(l1, l2, l3):
....: print(e1, e2, e3)
....:
3 1.5 9.1
6 1 3
1 0 2
중첩 리스트¶
리스트는 어떠한 객체도 포함할 수 있습니다. 따라서 리스트의 원소로 또 다른 리스트를 포함할 수 있습니다. 이러한 리스트를 중첩 리스트라고 합니다.
섭씨, 화씨 리스트 2개를 하나의 리스트로 담는 예입니다.
In [41]: Cdegrees = range(-20, 41, 5)
....: Fdegrees = [(9.0 / 5) * C + 32 for C in Cdegrees]
....:
....: table1 = [Cdegrees, Fdegrees] # list of two lists
....:
....: print(table1[0]) # Cdegrees 리스트
....: print(table1[1]) # Fdegrees 리스트
....: print(table1[1][2]) # Fdegrees의 3번째 성분
....:
range(-20, 41, 5)
[-4.0, 5.0, 14.0, 23.0, 32.0, 41.0, 50.0, 59.0, 68.0, 77.0, 86.0, 95.0, 104.0]
14.0
[섭씨, 화씨]
순서쌍의 리스트는 다음과 같이 만들 수 있습니다.
In [42]: table2 = []
....: for C, F in zip(Cdegrees, Fdegrees):
....: row = [C, F]
....: table2.append(row)
....: print(table2)
....:
[[-20, -4.0], [-15, 5.0], [-10, 14.0], [-5, 23.0], [0, 32.0], [5, 41.0], [10, 50.0], [15, 59.0], [20, 68.0], [25, 77.0], [30, 86.0], [35, 95.0], [40, 104.0]]
리스트축약을 이용하면 더 간단하게 만들 수 있습니다.
In [43]: table2 = [[C, F] for C, F in zip(Cdegrees, Fdegrees)]
....: table2
....:
Out[43]:
[[-20, -4.0],
[-15, 5.0],
[-10, 14.0],
[-5, 23.0],
[0, 32.0],
[5, 41.0],
[10, 50.0],
[15, 59.0],
[20, 68.0],
[25, 77.0],
[30, 86.0],
[35, 95.0],
[40, 104.0]]
중첩 리스트 접근¶
for C, F in table2:
# table2의 행 C 와 F
# 또는
for row in table2:
C, F = row
...
일반적인 중첩 리스트 접근¶
여러 개의 리스트를 포함하는 리스트 somelist[i1][i2][i3]...
의 접근 다음과 같습니다.
for i1 in range(len(somelist)):
for i2 in range(len(somelist[i1])):
for i3 in range(len(somelist[i1][i2])):
for i4 in range(len(somelist[i1][i2][i3])):
value = somelist[i1][i2][i3][i4]
# value를 이용해 작업
또 다른 방법으로는 다음과 같습니다.
for sublist1 in somelist:
for sublist2 in sublist1:
for sublist3 in sublist2:
for sublist4 in sublist3:
value = sublist4
# value를 이용해 작업
예를 들면 다음과 같습니다.
In [44]: L = [[9, 7], [-1, 5, 6]]
....: for row in L:
....: for column in row:
....: print(column)
....:
9
7
-1
5
6
튜플(tuple)¶
리스트와 같이 자료를 담을 수 있는 자료형으로 튜플(tuple)이 있습니다. 리스트와 다른 점은 리스트는 원소를 변경할 수 있지만 튜플은 변경할 수 없다는 것입니다.
In [45]: t = (2, 4, 6, 'temp.pdf') # 튜플 정의
....: t = 2, 4, 6, 'temp.pdf' # 소괄호는 생략해도 됩니다.
....: t[1] # 리스트와 동일하게 원소에 접근합니다.
....:
Out[45]: 4
리스트와 같은 연산들을 할 수 있습니다.
In [46]: t = t + (-1.0, -2.0) # add two tuples
....: t
....:
Out[46]: (2, 4, 6, 'temp.pdf', -1.0, -2.0)
In [47]: t[1] # indexing
Out[47]: 4
In [48]: t[2:] # subtuple/slice
Out[48]: (6, 'temp.pdf', -1.0, -2.0)
In [49]: 6 in t # membership
Out[49]: True
다음은 튜플의 원소들을 변경하려고 시도하기 때문에 에러가 발생합니다.
t[1] = -1
t.append(0)
del t[1]
튜플 사용¶
튜플은 변하지 않기 때문에 실수로 변경될 우려가 없습니다.
튜플이 리스트보다 빠릅니다.
파이썬 프로그래밍에서 광범위하게 사용됩니다.
리스트와는 다르게 사전형(딕셔너리)에서 키로 사용될 수 있습니다.
연습문제¶
화씨를 섭씨로 변경하는 프로그램을 작성하는데, 첫 번째 열은 0, 10, 20, …, 100 화씨를 출력하고 두 번째 열은 거기에 대응되는 섭씨 온도를 출력하는 프로그램을 작성하세요. while 문 예제를 수정하여 작성하세요.
위 1번 문제를 수정하여 출력되는 열을 하나 더 추가하여, 세번째 열에는 섭씨의 근사값 구하는 다음 공식
\[C \approx \hat{C} = (F - 30) / 2\]을 이용해서 근사값을 출력하는 프로그램을 작성하세요.
1부터 n까지 숫자 중에서 홀수만 출력하는 프로그램을 작성하세요. n이 홀수일 때는 바로 앞 홀수까지만 출력하도록 합니다. 첫 문장에 n의 값을 할당하고 시작하세요.
위의 프로그램을 수정해서 홀수를 리스트에 저장하는 프로그램을 작성하세요.
while
문을 이용하고 빈 리스트를 정의하고 그곳에 홀수들을 저장하도록 하세요.리스트 축약을 이용하여 홀수를 저장하는 리스트를 만드는 프로그램을 작성하세요.
2, 3, 5, 7, 11, 13
을 포함하는 리스트primes
를 만들고for
문을 이용하여 리스트의 원소들을 출력하는 프로그램을 작성하세요.1부터 n까지 더하는 프로그램을 작성하고 합의 공식 \(n(n+1)/2\)를 사용하여 맞는지 확인하세요.
구간 \([a, b]\)를 n+1 등분한 값을 리스트에 저장하는 프로그램을 다음과 같이 2가지 방법으로 작성하세요.
먼저 빈 리스트를 만들고 for 문을 이용하여 각 점들을 리스트에 넣도록 합니다. 힌트: 등간격 \(h = (b-a)/n\)을 구하고 각 점들 \(x_i = a + ih\), \(i=0, 1, \ldots, n\)을 계산합니다.
리스트축약을 이용하여 만들도록 합니다.
수직으로 초속도 \(v_0\)로 던져진 물체가 시각 \(t\) 일 때, 높이 \(y(t)\) 공식은 다음과 같습니다.
\[y(t) = v_0 t - \frac{1}{2} g t^2\]여기서 \(g = 9.8\) 중력가속도입니다. \(t\)가 구간 \([0, 2v_0/g]\)의 n+1 개의 등간격 점에서 시각 \(t\)와 높이 \(y(t)\)에 대한 테이블을 출력하는 프로그램을 작성하세요. 초속도 \(v_0 = 30\)로 놓고 계산하세요.
다음 프로그램을 실행했을 때 출력되는 결과를 설명하세요.
a = [1, 3, 5, 7, 11] b = [13, 17] c = a + b print('c=', c) b[0] = -1 d = [e+1 for e in a] print('d=', d) d.append(b[0] + 1) d.append(b[-1] + 1) print('d[-2:]=', d[-2:]) for e1 in a: for e2 in b: print('e1 + e2=', e1 + e2)
다음 프로그램은 합 \(\sum_{k=1}^M \frac{1}{k}\)을 구하는 프로그램입니다. 잘못된 곳을 지적하고 올바르게 고치세요.
s = 0 k = 1 M = 100 while k < M: s += 1/k print(s)
위 프로그램을
for
문을 이용해서 올바르게 작성하세요.range()
함수를 이용하세요.다음 코드는 이자를 계산하는 프로그램입니다. 출력되는 것이 무엇을 나타내는 것인지를 설명하세요.
initial_amount = 100 p = 5.5 # 이자율 amount = initial_amount years = 0 while amount <= 1.5 * initial_amount: amount = amount + p / 100 * amount years = years + 1 print(years)
다음 프로그램을 실행해보고 결과에 대해서 이야기해보세요.
a = 1/947.0*947 b = 1 if a != b: print('잘못된 결과입니다.')