(연재) 파이썬은 처음이라 – 문법은 처음이라 : 예제편

지난 번 문법에 대해 설명하면서, 각 문법의 패턴에 한정해서 설명하면서 코드 소개를 가능한 피했었다. 이번 글에서는 각 구문별 코드의 예제와 각각의 코드가 어떤식으로 실행되는지를 설명하는 시간을 갖도록 하겠다. 또 이 작성하는 예제코드에는 몇 가지 기본 입출력 관련 함수가 등장한다. 내장 함수에 대한 토픽을 따로 마련할 생각이지만, 워낙 기본적인 함수나 메소드들은 진도에 무관하게 그 때 그 때 소개하도록 하겠다. 먼저 기본적인 입출력 함수와 더불어서 간단한 바인딩 구문을 소개해보겠다.

먼저 두 개의 함수를 소개한다. input, print 라는 이름의 함수이다. 함수에 대한 자세한 설명은 일단 미루도록 하고, 파이썬에서 함수는 어떤 입력값을 받아서 내부에서 처리한 출력값을 반환하는 장치를 말한다. 파이썬 문법에서 함수는 그 이름 뒤에 괄호를 붙여서 표현하며, 인자값(arguments)을 받는 함수는 그 괄호안에 인자를 넣어서 호출한다.  input 함수는 인자 없이도 호출이 가능한 함수인데, 사용자로부터 입력된 한줄의 문자열을 리턴한다. 즉 input() 이라고 표현하면, 이 또한 표현식이며, 그 표현식은 사용자가 키보드를 두드려서 엔터까지 친, 사용자로부터 입력받은 문자열로 평가된다. input() 함수가 가장 기본적인 입력 함수라 한다면, 출력을 위해서는 print()라는 함수가 있다. print() 함수는 인자로 전달된 값을 문자열로 바꿔서 그 내용을 화면에 출력한다. print() 함수는 입력값이 뭐가되었든, 그 내용을 출력하고 표현식 자체는 None으로 평가된다.

 

name = input() #1
print(name) #2

이 두 라인의 간단한 코드는 하나의 완전한 프로그램이며 각각의 라인은 다음과 같이 해석된다.

  1. 첫 번째 라인의 구문 구조는 바인딩 구문(binding statement)이며, input() 함수의 결과값에 name이라는 이름을 붙인다.
  2. name의 값을 출력하기 위해 print 함수에게 name을 인자로 전달한다.

위 소스 코드를 print_name.py 라는 이름으로 저장하고 실행해보자. 프로그램을 실행하면 처음에 아무일도 일어나지 않는다. 단지 커서가 깜빡거릴 뿐이다. 하지만 우리는 이 때 콘솔에 키보드로 어떤 문자열을 입력할 수 있다. 아무 글자들이나 입력한 후에 엔터키를 누르면 방금 입력했던 내용이 그대로 출력된다.

첫번째 라인에서 input() 함수를 평가하는데에는 제법 긴 시간이 걸린다. 왜냐하면 이 함수는 “우리가 키보드로 입력한 값”으로 평가되어야 하기 때문에 실제로 엔터키를 입력하는 시점까지는 평가를 지연하고 기다리게 된다. 무엇이되었든 글자들을 입력하고 엔터키를 치게되면 다음과 같은 일들이 벌어진다.

  1. 바인딩 구문은 우변이 먼저 평가된다. input() 함수가 평가되면서 우리가 입력한 문자열 값이 된다.
  2. 좌변으로 바인딩되면서 name 이라는 이름이 그 문자열을 가리키게 된다.

어떤 이름이 값을 “가리킨다” 혹은 “참조한다”는 표현이 너무 추상적이고 어렵다면, 어떤 종이 상자에 문자열을 집어넣고 거기에 name 이라고 쓰여진 이름표를 붙여두었다고 생각하면 된다. (실제로 이 비유는 파이썬의 바인딩에 대한 엄청나게 적절한 비유이다.)

두번째 라인을 보자. 두 번째 라인은 그냥 표현식 하나가 달랑 쓰여 있다. print()라는 함수를 평가하는데, 괄호 안에 name 이라는 이름을 집어 넣었다. print() 함수는 “주어진 값을 문자열로 변환해서 화면에 출력한다”고 했다. 사실 값을 받는 것이 아니라, 값의 이름표를 받는다고 생각하면 된다. print() 함수의 내부에서는 name 이라는 이름표를 가지고, 좀 전에 문자열을 담아두었던 상자를 찾고, 그 내용물을 화면으로 출력한다.

이 두라인이 연속적으로 평가된, 최종 결과는 None 이다. 이 프로그램은 어떤 값도 만들어내지 않았지만, 프로그램의 외부 세계에 대해서는 “어떤 일”을 하였다. 프로그램 외부의 시선으로 바라봤을 때, 이 두줄 짜리 프로그램은 다음과 같은 일을 했다.

키보드를 두드린다 ==> { 마법같은 프로그램 } ==> 화면에 출력된다.

바인딩 구문을 사용하는 몇 가지 예를 더 보도록 하자.

x = 51
y = 43
z = (x + y) / 2  
print(z) 

프로그램을 실행하면 47.0이 출력된다.  첫 줄부터 세번째줄까지 3개 라인은 각각 바인딩 구문이다. 51 이라는 정수값에 x라는 이름을, 47이라는 정수값에 y라는 이름을 붙인 후, (x + y) / 2 라는 표현식을 평가하고 그 값을 z라는 이름에 바인딩했다. (그 결과는 47.0) 그리고 마지막 라인은 이 z를 출력하기 위해 print 함수를 호출했다.

정수를 입력받기

키보드를 통해서 입력 받은 숫자를 더하여 출력하는 프로그램을 작성해보자. 바로 위에서 input과 print 함수를 소개했고, 정수값은 더하기 연산을 할 수 있으니 간단하게 만들 수 있을 것 같다. 다음과 같이 말이다.

a = input()
b = input()
c = a + b
print(c)

뭔가 좀 이상하다. 프로그램을 실행하고 처음에 1을 입력하고 엔터, 그리고 2를 입력하고 엔터를 하면 3이 나와야 할 것 같지만 실제로는 12가 출력된다. 어디가 잘못되었을까? 바로 input()을 평가한 값의 타입을 잊었었던 것이다.

input 함수는 문자열을 리턴한다고 했다. 즉 input()의 표현식은 문자열타입 값으로 평가된다. 결국 1, 2를 각각 입력했다면 c = a + b 라는 구문은 c = "1" + "2" 이므로 "12"로 평가되고 그것이 출력된 것이다. 따라서 입력된 숫자를 가지고 정수값을 만들어줄 어떤 마법이 필요하다. 이 때 사용하는 마법은 바로 int() 함수이다.1 int() 함수는 정수로 바뀔 수 있는 어떤 것을 넣어주면 그것을 정수로 바꾼 값을 내놓는 함수이다.2  여기서 우리가 입력하는 글자들이 모두 숫자라면 실제로 정수를 만들어준다. 만약 “apple”, “banana”와 같은 단어를 입력하면? 글쎄 나는 그것을 정수로 바꾸는 방법을 모른다. 아마 파이썬 해석기도 그 방법을 모를 것이다. 숫자로 해석될 수 없는 문자를 집어넣으면 ValueError가 났다면서 프로그램이 중단될 것이다.

a = input()
x = int(a)
b = input()
y = int(b)
z = x + y
print(z)

이번에는 아주 잘 동작한다. 그런데 잠깐 여기를 보자. input()이라는 표현식은 문자열이라고 했다. 여기서는 그 값을 a라는 이름에 붙인 후 곧바로 다시 int()함수에 인자로 전달했다. 즉 함수의 인자로 전달 되는 것은 값이므로 이름 대신에 표현식을 그대로 쓸 수 있다. 즉, int(input()) 이라고 쓸 수 있다는 것이다. 같은 방식으로 z라는 이름을 보면, 이 이름은 중간 계산 결과를 가리키는 이름이다. 이 경우 z를 원래의 a + b로 치환하여  print(a + b) 라고도 쓸 수 있다.

a = int(input())
b = int(input())
print(a + b)

그렇다면, 다음과 같이도 쓸 수 있는 것 아닌가?

print(int(input()) + int(input())

맞다. 다만 이건 괄호가 너무 난무해서 약간 읽기가 힘들어진다. (사람에 따라서는 뭐 이정도는 쉬울지도 모르겠다.) 어떻게 쓰던지 모두 “정상적인” 코드이며 동작에 문제는 없다. 대신에 파이썬에서는 “간결하고 분명하고 읽기 좋은 것”이 가장 좋은 것이다. 어느쪽을 선호하든지 그것은 본인의 몫이다. 다만 첫번째 코드처럼, 축약할 수 있는 부분들까지 전부 무시하고 일일이 바인딩하고 쓰는 것은 그렇게 좋은 습관은 아니다. 그것이 매우 읽기 쉬운 것은 사실이나, 간단한 정보를 전달하기 위해서 너무 너저분하게 쓴다는 느낌을 준다.

그러면 어느 수준으로 축약하는 것이 좋을까? 그것은 “지금 어떤일을 하고 있는가”를 적절히 표현하는 수준에서 정하는 것이 맞다. 위 코드가 하는 일을 말로 표현하면 “두 개의 정수를 입력 받아, 그 합을 출력한다”이다. 따라서 두 개의 정수를 입력 받고, 더해서, 출력하는 수준을 코드로 표현하면 된다. 그리하면 세 번째의 세 줄로 표현된 코드가 가장 적당해 보인다.

IF문

IF문은 특정한 조건식에 따라서 프로그램의 진행 방향이 달라지는 분기문이라고 했다. 간단한 몇 가지 예를 들어보자. 다음은 입력한 값이 홀수인지 짝수인지를 판단하여 그 결과를 출력하는 프로그램이다.

n = int(input('숫자를 입력하세요')) #1
if n % 2 == 0: #2
  print("짝수입니다.") #3
else:
  print("홀수입니다.") #4

위 코드의 로직은 다음과 같다.

  1. 맨 처음에는 키보드로부터 수를 하나 입력받고, 계산을 위해서 정수로 변환했다.
  2. 짝수는 2로 나눈 나머지가 0인 수이다. 나머지 연산자를 써서 n % 2 를 구하고 그것이 0과 같은지 검사한다.
  3. 그 결과가 참이라면 “짝수입니다.”를 출력한다.
  4. 그 결과가 거짓이라면 “홀수입니다.”를 출력한다.

조건에 따라 분기한 후 다시 다른 조건으로 분기하는 경우도 생각할 수 있다. 예를 들어 2의 배수이면서 5의 배수인 수가 있다면 이 수는 2와 5의 공배수이며 즉 10의 배수가 된다. 이 과정을 표현해보자. 그리고 짝수가 아닌 경우에도 5의 배수가 된다면 이를 출력해보자.

n = int(input())
if n % 2 == 0:
  if n % 5 == 0:  #1
    print('10의 배수입니다.') #2
  print('짝수입니다.')  #3
elif n % 5 == 0:  #4
  print('5의 배수입니다'.) 
else: #5
  print('그냥 홀수입니다.')

위 코드가 실행되는 과정을 살펴보자.

  1. 먼저 n이 짝수로 판정된다면 다시 5의 배수인지를 검사받는다.
  2. 짝수이면서 5의 배수이므로 “10의 배수입니다”가 출력된다.
  3. 이 문장은 5의 배수 조건문의 블럭이 아니다. 따라서 10의 배수여부에 상관없이 짝수라면 항상 출력된다. 만약 n이 10의 배수라면 “10의 배수입니다.”와 “짝수입니다.”가 나란히 출력될 것이다.
  4. 짝수가 아니라면 5의 배수인지 다시 검사한다.
  5. 짝수도 아니고 5의 배수가 아니라면 “그냥 홀수입니다”가 출력된다.  4번에서 “5의 배수입니다”가 출력되었다면, 이 문장은 출력되지 않을 것이다.

ELIF 절을 사용해야 하는 가장 대표적인 문제는 주어진 점수에 대해서 점수 구간을 두고 평점을 계산하는 프로그램이다.

어떤 학교의 평점은 A, B, C, D, F로 나뉘어집니다. 이 평점은 시험 점수의 구간에 따라 구해집니다. 각 구간은 다음과 같습니다.

  • 50점 미만인 경우 F를 받습니다.
  • 50점 이상 65점 미만인 경우 D를 받습니다.
  • 65점 이상 75점 미만인 경우 C를 받습니다.
  • 75점 이상 85점 미만인 경우 B를 받습니다.
  • 85점 이상인 경우 A를 받습니다.

먼저 특정 구간에 대해 어떤 값이 있는지를 어떻게 검사하는지 살펴보자. “50점 이상 65점 미만”인 경우를 어떻게 체크할까?

  • 점수값을 N 이라 하자
  • “50점 이상”은 N >= 50 으로 표기할 수 있다. 혹은 방향을 바꿔서 50 <= N 으로 표기할 수 있다.
  • “65점 미만”은 N < 65로 표기할 수 있다.
  • 50점 이상, 65점 미만은 위의 두 조건을 동시에 만족해야 한다. 예를 들어 70점은 65점 미만의 조건을 만족하지 않기 때문에 이 범위에 들지 않는다.
  • 각각의 부등식은 참/거짓으로 판단되며, 두 부등식을 동시에 만족해야 하는 경우 and를 사용해서 결합한다.
  • 따라서 N >= 50 and N < 65 라고 쓸 수 있다.
  • 그런데, 파이썬의 부등식은 연쇄적으로 결합할 수 있다. 따라서 50 <= N < 65 로 쓰는 것 역시 허용된다.

그렇다면 다음과 같이 if, elif, else를 써서 코드를 작성할 수 있을 것이다.

n = int(input())
if n < 50:
  print("F")
elif 50 <= n < 65:
  print("D")
elif 65 <= n < 75:
  print("C")
elif 75 <= n < 85:
  print("B")
else:
  print("A")

다만, 하나의 구간에 대해서 50 <= n < 65를 보는 것은 맞는데, 이 로직을 따라가보면 우선 50점 미만인지 체크한 다음에 두 번째로 50이상 65미만 조건을 체크한다. 만약 N이 50 미만이었다면 앞의 IF 절에서 분기했기 때문에 50이상이라는 조건을 이미 만족하는 상태로 ELIF 절을 만난다. 따라서 각 ELIF 절의 맨 왼쪽 부등식은 사실은 항상 참이 되므로 필요없는 구문이된다. 즉 elif n < 65: 만 있어도 이 전체 로직은 문제없이 작동할 것이다.

WHILE 문

WHILE 문은 특정 조건을 만족하는 한 루프를 계속 반복하라는 구문이다.  WHILE 문의 블럭 내에서는 특정한 값을 변경하는 동작을 포함하며, 보통 이 변경되는 값 중의 하나를 루프의 종료 조건으로 사용한다. WHILE문을 이용해서 1부터 10까지의 자연수의 합을 구해서 출력하는 코드를 작성해보겠다.

s = 0
i = 1
while i <= 10:
  s += i
  i += 1
print(s)

이 코드에 대한 설명이다.

  • 먼저 s는 0으로 초기화하는데, 각 자연수를 누적해서 더한 값을 가리키는 이름이다.
  • i는 매번 증가하는 자연수가 된다. 그 초기값은 1이다.
  • while i <= 10: 을 통해서 i 가 10 이하인 경우에 계속 반복한다는 것을 지정한다.
  • s 는 i 만큼 증가하고,
  • 다시 i는 1씩 증가한다.
  • i 가 10일 때 s 에 한 번 더해진 후, i += 1 을 거쳐서 11이 될 것이다.
  • i가 11이 되면 조건을 더 이상 만족하지 않기 때문에 블럭은 더 이상 실행되지 않고 건너뛰게 된다.
  • s가 출력된다.

WHILE문의 조건이 블럭 외부에 있을 때도 있지만, 블럭 내부에서 정의되는 값이라면 조건절에 걸 수 가 없다. 예를 들어 5보다 큰 수가 입력되는 동안 입력된 값을 출력하려고 한다면,

n = int(input())
while n > 5:
  print(n)
  n = int(input())

똑같은 구문을 WHILE 블럭 안과 밖에 같이 써야 한다. 이것은 단지 WHILE의 조건절에 필요하기 때문에 이렇게 쓴 것이다. 이런 경우에는 무리해서 종료 조건값을 앞에서 정의하지 않고 while True: 로 무한 루프를 만들고, 반복 블럭 내에서 if + break로 탈출하는 패턴을 사용한다.

while True:  #1
  n = int(input())  #2
  if n <= 5:  # 3
    break
  print(n)  #4
  1. while True: 에서 보듯 조건은 항상 참이므로 이 루프는 무한루프를 돌게 된다.
  2. n은 블럭 내에서 처음 선언된다.
  3. 조건식을 통해서 break로 빠져나가는 길을 만들어 놓고
  4. 조건을 만족하지 않으면 출력한 후에 다시 while로 돌아간다.

CONTINUE 구문의 경우 잘 쓰면 코드를 깔끔하게 하는데 도움이 될 수 있다.  아래 코드가 어떤 일을 하는지 살펴보자.

i = 0
while i < 50:
  i += 1
  n = int(input())
  if n < 10:
    continue
  m = int(input())
  print(m + n)
  1. i 와 i < 50 으로 보아, 이 반복은 50번 동안 반복하게 된다.
  2. 루프를 시작하면 시행 카운터인 i 값을 올리고,
  3. 정수 하나를 입력받는다. (n)
  4. 입력받은 정수가 10보다 작으면 이후 작업을 생략하고 whie로 돌아간다.
  5. 입력받은 정수가 10이상이면, 또 다른 정수를 하나 더 입력받고
  6. 그 합을 출력한다. 그리고 다시 while로 돌아간다.

WHILE 문 정리

while문은 반복되는 참인동안 반복되는 if문이라고 생각하면 된다. 마지막 예제와 같이 특정 횟수만큼 반복되는 경우에는 for 문을 사용하는 것을 추천한다. 코드 자체가 간결해지는 효과도 있으면서, 흔히 하기 쉬운 실수를 방지할 수 있다. while 문을 사용할 때 흔히 하기 쉬운 실수로는 위의 경우에 i += 1 을 쓰는 것을 깜빡하고 빼먹어서 무한 루프를 돌게 된다거나, 종료 조건에서 i < 50 이라고 써야 할 부분을 i <= 50 이라고 쓰거나 혹은 그 반대로 써서 정확한 횟수만큼 반복하지 못하는 경우들이 있다.

따라서 예외적으로 전체 반복횟수를 알 수 없는 경우에 while문을 쓸 것.  그리고 가급적이면 탈출 조건을 명확하게 하기 위해서 중도에 탈출하는 무한루프의 형태로 사용하는 것을 권한다. 따라서 보다 권장되는 코딩 습관에 따라 위 코드를 다시 쓰면 다음과 같다. (그리고 억지로 continue문을 썼지, 이 문제는 continue가 없어도 된다.)

i = 0
while True:
  ## 탈출조건을 확인하고
  if i >= 50:
    break
  ## 탈출이 아닌 경우 조건 변수값을 변경한다.
  ## 이후, 반복 코드를 작성한다.
  i += 1
  n = int(input())
  if i > 10:
    m = int(input())
    print(m + n)

FOR 구문

FOR문은 파이썬에서 가장 유용하며 중요한, 강력한 반복구문이다. 파이썬에는 여러가지 타입의 “반복가능한” 값들이 있는데, FOR 문은 이 반복가능한 값에 대해서 매 반복을 시행하는 구문이다. 파이썬의 반복가능한 값에 대해서는 별도의 토픽에서 따로 설명하도록 하고 여기서는 간단한 FOR 문의 예제 몇 가지를 보도록 하자.

FOR문에서 일반적으로 가장 흔히 만나는 함수가 하나 있는데, 바로 range() 함수이다. 이 함수는 특정한 정수값 사이의 범위를 만드는데, 이 때 만들어지는 값이 반복가능한 값이다. range() 함수는 다음과 같은 세 가지 사용 방법이 있다.

  • range(10) : 0, 1, 2,… ,9까지의 10개의 값 범위를 만든다. 중요한 것은 10으로 주어지는 종료값은 범위에 포함하지 않으며, 범위의 시작이 0이라는 점이다. 따라서 범위에는 종료값은 포함되지 않지만, 전체 범위의 정수값은 종료값과 같은 개수를 가진다. (종료값이 범위에 포함되지 않는 것은 파이썬 여러 문법에서 일관적으로 나타나는 특성이다)
  • range(3, 10) :  이렇게 쓰이는 경우에 첫번째 값인 3은 시작값이며, 두 번째 값인 10은 종료값이다. 이 때에도 10은 포함되지 않으므로 이 범위는 실제로 3, 4, 5, 6, 7, 8, 9 가 해당한다.
  • range(3, 10, 2) : 종료값 뒤에 값을 하나 더 쓰면 이것은 간격으로 취급된다. 이 범위는 3, 5, 7, 9로 시작값으로부터 종료값보다 작은 범위 내에서 간격만큼 늘어난다. 참고로 간격이 음수로 주어지는 경우에는 시작값이 종료값보다 커야 한다. range(10, 3, -2)는 10, 8, 6, 4의 범위를 가리킨다.

즉, 복잡한 기술적인 개념이 없이, range() 함수는 특정한 범위의 연속적인 수열을 만들어내는 함수라고 생각하면 된다. 그 결과는 수열의 각 항에 대해서 반복가능한 값이다. 따라서 for 문은 range() 함수와 흔히 같이 쓰인다. 다음은 0~9까지의 정수를 출력하는 코드이다.

for i in range(10):
  print(i)

이 코드는 이렇게 이해하면 된다.

  1. range(10) 에 의해서 0, 1, 2, … , 8, 9의 정수들이 준비된다.
  2. i 는 매번 각각의 정수값이 되어 print(i)는 이를 출력하게 된다.
  3. 준비된 값들을 모두 사용하고나면 for 루프가 종료된다.

만약 이 코드와 동일한 동작을 하는 while 문 코드를 쓴다면 다음과 같을 것이다.

i = 0
while i < 10:
  print(i)
  i += 1

for i in range(10): 이라는 표현이 낯설어서 어렵게 느껴질 수 있겠지만, 이 FOR문은 WHILE문보다 훨씬 간결하다. 종료조건과 조건값의 갱신을 매번 수동으로 지정할 필요가 없으며, 따라서 이 과정에서 발생할 수 있는 실수의 여지가 없어진다.  FOR문을 쓰기 위해서는 IN 절에 사용할 반복가능한 어떤 값이 필요하지만, 이미 존재하고 있는 값을 쓰거나, range()를 이용해서 간단하게 정의할 수 있기 때문이다.

for 문의 본체가 되는 블럭은 해당 for 문에 의해서 반복되며, 블럭 내에는 또다른 if, while, for 문이 올 수 있다.  다음의 예는 구구단을 2단부터 9단까지 출력하는 예이다.

for x in range(2, 10): #1
  print(x, '단')  #2
  for y in range(2, 10): #3
    print(x, '*', y, '=', x * y) # 4
  print() #5
  1. x는 2~9사이의 범위이다. 이 코드에서 x는 2단, 3단, 4단..의 단을 의미한다.
  2. 각 단을 출력하기에 앞서서 ‘2 단’과 같이 현재 출력할 단의 이름을 한 번 출력한다. print() 함수는 컴마로 구분되는 여러 개의 인자를 넣어줄 수 있다. 각 인자는 공백으로 분리되어 순서대로 출력된다.
  3. y는 다시 2~9사이의 범위이다. 이 반복문은 각 단에 대해서 매번 반복되며, 각 단의 대표 숫자를 몇 배 할 것인지를 나타내는 값이다.
  4. print() 문을 사용해서 각 라인을 출력한다. x는 현재단의 값으로 고정되며, y는 각 단에서 2~9로 바뀌어나간다. x * y를 계산하여 그 결과까지 출력하게 된다.
  5. 각 단의 출력이 끝나면 구분을 위해서 빈 줄을 하나 출력할 것이다. print()에 아무런 값이 전달되지 않으면 빈 줄만 출력된다.

이 와 똑같은 동작을 하는 코드를 while 문을 쓴다면 어떨까? 먼저 각자가 한 번 코드를 작성해서 출력해보자. 그리고 단 한번에 제대로 출력되는 코드를 작성하였는지 체크해보자.

x = 2
while x < 10:
  print(x, '단')
  y = 2    ## 매 단마다 y를 초기화해야 한다. 이 위치가 틀리면 어이없는 결과가 출력된다.
  while y < 10:
    print(x, '*', y, '=', x * y)
    y += 1  ## 우주끝까지 출력하고 싶지 않다면 y를 잘 업데이트하라
  x += 1    ## 같은 이유로 x도 빼먹지 않고 업데이트를 잘해야 한다.

특히 이처럼 반복문이 중첩되는 경우에 WHILE 문이라면 조건을 변경시키는 코드의 위치가 잘못되거나, 아예 이런 코드를 빼먹기 쉽다. 따라서 앞으로는 피할 수 없는 상황이 아니면 WHILE 문은 쓰지 않는 것으로 알고 있자.

FOR – IN 문에서 사용되는 반복가능한 값에는 range 객체(range() 함수가 리턴하는 값)외에도 리스트나, 문자열, 집합, 사전…등 단일 값이 아닌 여러 원소의 집합으로 간주되는 값이 올 수 있다. 이러한 “반복가능한” 값을 파이썬에서는 연속열, 즉 시퀀스(sequence)라고 한다. 시퀀스는 그 정확한 타입을 막론하고 반복가능한(iterable) 공통적인 특성을 갖는다. 어떤 리스트 A의 각 원소에 대해서 그 제곱의 값을 출력하는 코드를 보자.

A = [3, 7, 2, 9, 4]
for a in A:
  print(a * a)

반복문의 관점에서 for 는 어떤 연속열의 각 원소에 대해 동일한 작업을 반복하는 것으로 볼 수 있는데, 한 편으로는 다음과 같이 생각할 수 있다.

  • 리스트나 그외 다른 연속열들은 결국 하나의 값이며, for 문은 이러한 연속열 하나에 대해서 어떤 코드 블럭을 그 내부로 밀어넣어 모든 원소가 동일한 변형을 적용받도록 하는 연산이다.
  • range에 대해서 생각해보면, 이는 기본적으로 하나(혹은 두 세 개)의 정수값으로부터 여러 개의 정수값을 만들어내는 역할을 담당한다. 즉 하나의 값이 여러 개의 값으로 populating되게 하는 문맥으로 이해할 수 있다.

  1. 앞으로 함수와 같이 실행가능한 이름을 언급할 때에는 ()를 뒤에 붙이도록 하겠다. 
  2. 여기서 함수는 어떤 값 -(변환)-> 다른 값으로 만드는 변환장치의 역할을 한다. 너무나 기초적인 비유라 보통 이 중요성을 잊기 쉬운데 여기에 주목하는 습관을 가지도록 하자.