루프(Loop)

시퀀스 자료형을 for 문 또는 while 문과 조합하여 사용하면 간단하지만 강력한 루프 프로그래밍을 완성할 수 있다. 특히 range 또는 xrange 함수를 유용하게 활용할 수 있다.

for 문 루프

리스트 활용


In [1]:
animals = ['cat', 'dog', 'mouse']

In [2]:
for x in animals:
    print("This is the {}.".format(x))


This is the cat.
This is the dog.
This is the mouse.

서식 있는 print 문

위 코드에서는 서식이 있는 print문(formatted print)을 사용하였다. 사용방식은 원하는 곳에 중괄호({})를 위치시킨 후에 사용된 중괄호 개수만큼 format 키워드의 인자를 넣어주면 된다.


In [3]:
for x in animals:
    print("{}!, this is the {}.".format("Hi", x))


Hi!, this is the cat.
Hi!, this is the dog.
Hi!, this is the mouse.

아래와 같이 인덱싱을 이용하는 방식으로도 사용할 수 있다. 서식이 있는 print문에 대해서는 이후에 보다 다양한 예제를 살펴볼 것이다.


In [4]:
for x in animals:
    print("{1}!, you are {0}.".format("animals", x))


cat!, you are animals.
dog!, you are animals.
mouse!, you are animals.

문자열 활용

문자열을 이용하여 for문을 실행하면 하나씩 보여준다.


In [5]:
for letter in "Hello World":
    print(letter)


H
e
l
l
o
 
W
o
r
l
d

range 함수

일정한 순서로 이루어진 리스트는 range 함수를 이용하여 생성할 수 있다.


In [6]:
a = range(10)
a


Out[6]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  • 파이썬 2.x 버전에서는 range와 거의 동일한 역할을 수행하지만 리스트 전체를 보여주지 않는 xrange가 있다.
  • xrange(n)이 리턴하는 리스트의 원소들은 인덱싱을 통해서만 확인할 수 있다.
  • xrange는 굳이 원소 전체를 알 필요가 없고 단순히 카운팅만이 필요할 경우 보다 range보다 빠르게 리스트 원소에 접근하여 프로그램의 실행속도를 증가시키는 데에 활용할 수 있다.
  • 주의: 파이썬 3.x 버전부터는 xrange 함수가 사용되지 않는다. range 함수만 사용할 것을 추천한다.

In [7]:
b = xrange(10)
b


Out[7]:
xrange(10)

In [8]:
a[5]


Out[8]:
5

In [9]:
b[5]


Out[9]:
5
주의: xrange를 사용해서 만든 리스트에는 슬라이싱을 적용할 수 없다. 즉, 인덱싱만 사용한다.

In [10]:
a[2:6]


Out[10]:
[2, 3, 4, 5]

range 함수 인자

인자를 최대 세 개까지 받을 수 있다. 각 인자들의 역할은 슬라이싱에 사용되는 세 개의 인자들의 역할과 동일하다.

  • range([start,] stop [, step])
  • start의 경우 주어지지 않으면 0을 기본값으로 갖는다.
  • step의 경우 주어지지 않으면 1을 기본값으로 갖느다.

In [11]:
c0 = range(4)
c0


Out[11]:
[0, 1, 2, 3]

In [12]:
c1 = range(1, 4)
c1


Out[12]:
[1, 2, 3]

In [13]:
c2 = range(1, 10, 2)
c2


Out[13]:
[1, 3, 5, 7, 9]

range 함수는 for문에서 유용하게 활용된다.


In [14]:
for i in range(6):
    print("the square of {} is {}").format(i, i ** 2)


the square of 0 is 0
the square of 1 is 1
the square of 2 is 4
the square of 3 is 9
the square of 4 is 16
the square of 5 is 25

단순한 카운트 역할을 수행하는 용도로 range함수를 활용할 수도 있다.


In [15]:
for i in range(5):
    print("printing five times")


printing five times
printing five times
printing five times
printing five times
printing five times

C 또는 Java 언어에서와는 달리 파이썬에서는 for문에서 사용되는 변수는 지역변수가 아님에 주의할 것.


In [16]:
i


Out[16]:
4

range 함수 활용

연습: range 활용

함수 range_doublerange 함수와 비슷한 일을 한다. 대신에, 각 원소의 값을 두 배로 하여 리스트를 생성하도록 한다.

>>> range_double (4) 
[0, 2, 4, 6]
>>> range_double (10)
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

In [17]:
def range_double(x):
    z = []
    for y in range(x):
        z.append(y*2)
    return z

range_double(4)


Out[17]:
[0, 2, 4, 6]

연습: range 활용

서양에서는 숫자 13에 대한 미신이 있다. 따라서 동양에서 건물에 4층이 없는 경우가 있는 것처럼 서양에는 13층이 없는 경우가 있다. 아래 함수는 13을 건너 뛰며 리스트를 생성하여 리턴한다.


In [18]:
def skip13(a, b): 
    result = []
    for k in range (a,b):
        if k == 13:
            pass # 아무 것도 하지 않음
        else: result.append(k)
    return result

In [19]:
skip13(1, 20)


Out[19]:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19]

연습: 큐를 이용하여 은행대기 및 호출 프로그램 생성

리스트를 활용하여 큐(queue) 자료구조를 구현할 수 있다. 큐를 구현하기 위해서는 보통 다음 함수들을 함께 구현해야 한다.

  • add(name): 새로운 손님이 추가될 경우 손님의 이름을 큐에 추가한다.
  • next(): 대기자 중에서 가장 먼저 도착한 손님 이름을 리턴한다.
  • show(): 대기자 명단을 보여(print)준다.
  • length(): 대기자 수를 리턴한다.

준비사항:

  • q = []를 전역변수로 선언하여 활용한다.
  • 큐(queue) 자료구조의 활용을 이해할 수 있어야 한다.
    • 선입선출(FIFO, First-In-First-Out) 방식을 사용한다.

In [20]:
q = []

In [21]:
def add(name):
    q.append(name)

def next():
    return q.pop(0)

def show():
    for i in q:
        print(i)
        
def length():
    return len(q)

In [22]:
add("SeungMin")

In [23]:
q


Out[23]:
['SeungMin']

In [24]:
add("Jisung")

In [25]:
q.pop(1)


Out[25]:
'Jisung'

In [26]:
q


Out[26]:
['SeungMin']

In [27]:
next()


Out[27]:
'SeungMin'

In [28]:
add("Park")

In [29]:
add("Kim")

In [30]:
q


Out[30]:
['Park', 'Kim']

In [31]:
show()


Park
Kim

In [32]:
length()


Out[32]:
2

In [33]:
next()


Out[33]:
'Park'

In [34]:
add("Hwang")

In [35]:
show()


Kim
Hwang

In [36]:
next()


Out[36]:
'Kim'

In [37]:
show()


Hwang

연습: range 이용 함수호출 반복하기

  • 파이썬 함수를 다른 함수의 인자로 사용할 수 있다.
  • C 또는 Java 언어에서는 포인터를 사용해야함 가능하다.
  • 함수를 인자로 사용할 수 있는 언어를 고차원 언어라 한다.

예제: 아래 iterate 함수는 특정 함수 f를 인자 xn번 반복적용한 결과를 리턴하는 함수이다.


In [38]:
def iterate(f, x, n):
    a = x
    for i in range(n):
        a = f(a)
    return a

# 반 나누기를 원하는 만큼 반복하고자 하면 f 인자에 아래 divide_2 함수를 입력하면 된다.

def divide_2(x):
    return x/2.0

iterate(divide_2, 64, 3)


Out[38]:
8.0

while 문 루프

for 문과 while 문의 차이점

  • for문은 특정 구간(보통 시퀀스 자료형으로 표현됨) 내에서 움직이는 동안 일을 반복해서 진행함
  • while문은 특정 조건(불값으로 표현됨)이 만족되는 동안 일을 반복해서 진행함

In [39]:
x = 64
while x > 1:
    x = x/2
    print(x)


32
16
8
4
2
1

예제

컴퓨터가 다룰 수 있는 실수형 숫자 중에서 절대값이 가장 작은 숫자의 근사값 구하기

  • 보통 컴퓨터가 다룰 수 있는 가장 큰 숫자는 어느정도 들어서 알고 있다.
  • 반면에 컴퓨터가 다룰 수 있는 가장 작은 양의 실수도 존재한다.
  • 컴퓨터는 무한히 0에 가까워지는 실수를 다를 수 없다.
  • 매우 큰 수를 다룰 때와 마찬가지로 절대값이 매우 작은 실수를 다룰 때에도 조심해야 함을 의미한다.
  • 이는 컴퓨터의 한계때문이지 파이썬 자체의 한계가 아니다. 모든 프로그래밍언어가 동일한 한계를 갖고 있다.

In [40]:
eps = 1.0

while eps + 1 > 1:
    eps = eps / 2.0

eps + 1 > 1

# print("A very small epsilon is {}.".format(eps))


Out[40]:
False

연습문제

양의 정수 n을 입력 받아 0n 사이의 값을 균등하게 n분의 1로 쪼개는 숫자들의 리스트를 리턴하는 함수 n_divide을 작성하라.

견본답안 1


In [1]:
def n_divide(n):
    a = [] 
    for i in range(n+1):
        d = 1-(float(n-i)/n)
        a.append(d)
    return a

n_divide(10)


Out[1]:
[0.0,
 0.09999999999999998,
 0.19999999999999996,
 0.30000000000000004,
 0.4,
 0.5,
 0.6,
 0.7,
 0.8,
 0.9,
 1.0]

[0.0, 0.1, 0.2, 0.3, ..., 0.9, 1.0]을 기대하였지만 다르게 나왔다. n_divide 함수를 아래와 같이 코딩해 보자.

견본답안 2


In [3]:
def n_divide1(n):
    a = [] 
    for i in range(n+1):
        d = (float(i)/n)
        a.append(d)
    return a

n_divide1(10)


Out[3]:
[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]

견본답안 1과 2의 결과가 다르게 행동하는 이유는 아래와 같다.

  • 실수의 빼기 연산은 좀 복잡하다.
  • ab가 양의 실수라 가정하자.
  • a - b를 계산할 때 a + (-b)로 바꾸어 계산한다.
  • -b를 먼저 계산한다. 이때 좀 복잡한 방식으로 계산한다.
  • 따라서 견본답안 1과 같은 현상이 발생할 수 있다.