본문 바로가기
프로그래밍/파이썬 공부하기

Python 공부 - 2 (if문, for문)

by _OlZl 2024. 1. 23.

2024.01.21 - [프로그래밍/파이썬 공부하기] - 파이썬 공부하기 - 1 (자료형)

 

파이썬 공부하기 - 1 (자료형)

2024.01.21 - [프로그래밍/파이썬 공부하기] - 파이썬 공부하기 - 0 (시작) 파이썬 공부하기 - 0 (시작) 학교에서 1년 동안 C를 배웠습니다. C를 배우며 컴퓨터 언어의 기본적인 요소에 대해서도 잘 알게

olzl07.tistory.com

오늘도 계속해서 파이썬 공부를 해볼겁니다. 저번에는 자료형, 그 중에서도 특히 문자열에 중점을 뒀다면 오늘은 if문for문, 그 중 for문을 좀 집중적으로 다뤄볼겁니다. 

 

사실 if문과 for문은 단순하기 때문에 다룰 게 많지 않습니다. 그러나 C만 계속하다 파이썬을 쓴지 얼마 되지 않은 저는 애석하게도 리스트 컴프리헨션 할 때 쓰는 for문이 어색하게 느껴져 자유자재로 선언하지 못한다는... 문제가 있습니다. 따라서 파이썬의 for문 선언 등에 대한 내용을 중점적으로 다루겠습니다.

 

 + 조사하면서 공부를 해보니까 for문과 if문을 한 줄로 처리하는 간단한 코드 작성법이 있길래 재밌어보여서 이것도 다뤄보겠습니다.


if문

먼저, if문입니다. 사실 if문 같은 경우에는 C든 파이썬이든 JAVA든 심지어 Kotlin이든 모두 다 문법이 똑같은 정말정말 기특하고 고마운 녀석입니다. 그래서 딱히 다룰 것은 없지만 그래도 파이썬만의 차이점에 대해 조금은 이야기해보겠습니다.

 

  • 괄호 X

먼저, 파이썬의 경우에는 C와 달리 if 뒤의 조건에 괄호가 필요하지 않습니다. 물론, 넣어도 작동은 합니다만 가끔 괄호를 넣으면 에러가 뜨기도 하더라고요..?

가급적 넣지 않는 걸 추천드립니다.

if score > 90 :
  print("A Grade")

 

  • else if vs elif

if와 else 이외의 조건을 쓸 때 C에서는 else if를 사용합니다. 그러나 파이썬에선 이를 좀 더 줄여 elif를 사용합니다. 그냥 쓰는 글자가 다르단 것 말고는 차이점이 전혀 없으니 else if가 아니라 elif라는 것만 인지하시면 될 듯합니다.

elif score > 80 :
  print("B Grade")

 

  • and, or, not

C에서는 and, or, not의 의미를 표현하기 위해 각각 &&, ||, != 이 기호들을 사용합니다. 그러나 파이썬에서는 글자 그대로 and, or, not을 사용해 이 의미를 전달할 수 있습니다. 덕분에 조건 여러개가 나와도 C에서처럼 더럽게 괄호를 6~7개씩 써가며 &&, || 등을 붙일 필요는 없습니다. (저는 처음 이 사실을 알고 감격의 눈물에 젖었습니다.) 

그나마 not이 좀 생소해서 모르실수도 있을 것 같은데 not은 그냥 실제 결과가 False이면 True를 전달하고, 실제 결과가 True이면 False를 전달하는 것입니다.

if score < 80 and score > 70 :
  print("C Grade")

 

  • { } vs :

마지막 차이점입니다. C에서는 조건에 괄호를 붙이고 해당 조건에서 실행할 코드를 { }로 덮지만, 파이썬에서는 조건 뒤에 : (콜론)을 붙이고 줄을 내려 해당 조건에서 실행할 코드를 씁니다.

 

if문은 여기서 끝입니다. 정말 할 게 없습니다...


for문

드디어 for문입니다. 사실 for문도 일반적인 선언은 C와 동일하므로 대충 하겠습니다.

 

  • 일반적인 for문 선언

그냥 일반적인 for문은 C와 문법구조가 비슷합니다. 다만 C에서는 역시 괄호를 쳐서 변수, 조건, 증감을 설정해줬다면 파이썬에서는 괄호 없이 변수, 조건, 증감을 설정해준다는 것이 차이가 있습니다.

#include <stdio.h>

int main() {
  for (int i = 0; i <= 10; i++) {
    printf("%d\n", i);    
  }  
}
for 변수 in 이터러블 : 
    수행할 문장 1
    수행할 문장 2
    수행할 문장 3

(이터러블은 리스트, 튜플, 딕셔너리 등 반복문을 사용할 수 있는 객체를 의미합니다.)

 

이러한 for문을 선언할 시 리스트, 튜플, 문자열 등의 첫 번째 요소부터 마지막 요소까지가 '변수'에 대입되어 아래 문장들이 수행됩니다.

 

(튜플, 리스트에 대해서는 나중에 자세하게 다루겠습니다. 일단은 그냥 값들이 여러 개 저장되어 있는 거라고만 알고 계셔도 됩니다.)

 


for문 응용

num = ['one', 'two', 'three']
for i in num :
  print(i)
one
two
three

num 리스트의 첫 번째 요소부터 마지막 요소까지가 (one, two, three) 'i'에 대입되어 아래 문장이 수행됩니다.

 

i 자리에 여러 개의 변수를 넣을 수도 있습니다.

num = [(1, 2), (3, 4), (5, 6)]
for i, j in num :
  print(i + j)
3
7
11

range

사실상 for문을 쓸 때 가장 많이 함께 쓰는 구문인 range입니다.

저도 이번에 공부하면서 처음 알았는데 사실 range 함수는 리스트를 자동으로 만들어주는 기능을 합니다.

range(시작값, 끝값, 간격)

 

다음과 같은 문법을 통해 range 함수를 사용할 수 있습니다.

range 함수를 시작하면 [시작값 ~ 끝값 - 1] 의 요소들을 갖는 리스트가 생성됩니다.

시작값이 끝값보다 커도 되고 그럴 경우에는 간격이 음수로 진행돼야 합니다.

 

ex) range(1, 10)은 1부터 9까지의 숫자를 데이터로 갖는 리스트를 일시적으로 생성하는 겁니다.

for i in range(1, 10) :
  print(i)
1
2
3
4
5
6
7
8
9
10

 

range 함수를 쓸 때 굳이 저 세개의 값을 다 넣을 필요도 없습니다.

위에서 봤듯 숫자 2개만 넣어두면 자동으로 간격은 1로 지정됩니다.

또, 값을 하나만 넣으면 시작값은 자동으로 0, 간격은 1로 지정되어 끝값만 지정됩니다. 따라서 그냥 넣어준 숫자만큼 반복되는 효과를 냅니다.

for i in range(5) :
  print("_OlZl")
_OlZl
_OlZl
_OlZl
_OlZl
_OlZl

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

드디어 제 골머리를 그렇게나 썩이던 리스트 컴프리헨션입니다.

리스트 컴프리헨션은 간단히 얘기하자면 그냥 리스트 [ ] 안에 for문을 집어넣는 겁니다. 리스트 안에 for문을 넣음으로써 원래는 여러 줄이었던 코드를 간단히 한 줄로 줄일 수 있습니다.

사실 for문에서 설명하기보다는 리스트 생성이므로 리스트 설명할 때 소개하는게 더 정확하겠지만 그래도 for문이 들어가기도 하고, 제가 이걸 몰라서 for문을 어려워했으므로 여기서 다뤄보겠습니다.

 

찾다보니 딕셔너리 컴프리헨션, 셋 컴프리헨션 등도 있지만 차피 다 거기서 거기이므로 딕셔너리, 셋 공부할 때 대충 알아보도록 하고 이번에는 리스트 컴프리헨션만 다루겠습니다.

 

사용법은 다음과 같습니다.

[표현식 for 아이템 in 이터러블]

 

예를 한 번 들어보겠습니다.

만약 0~9까지의 수를 각각 제곱한 값의 리스트를 만들어서 출력하고 싶은데, 일반적인 for문을 사용한다면 아래와 같은 코드를 짜야합니다.

square = []

for i in range(10) :
  square.append(i**2)

print(square)

리스트를 만들어서 출력만 하는데 코드가 4줄이나 들어갔죠.

근데 리스트 컴프리헨션을 사용하면 이 코드를 간결히 줄일 수 있습니다.

square = [i**2 for i in range(10)]
print(square)

 

심지어 print와 합치면 1줄로도 줄일 수 있습니다.

print([i**2 for i in range(10)])

 

이렇게 반복문을 단순히 하여 리스트 관련 작업을 하는 것이 바로 리스트 컴프리헨션입니다.

 

만약 이중 for문을 써야한다면 어떨까요.

2단부터 9단까지의 구구단을 출력해주는 코드를 이중 for문을 이용해 짜면 다음과 같습니다.

gugudan = []

for i in range(2, 10) :
  for j in range(1, 10) :
    gugudan.append(i*j)

print(gugudan)

 

그러나 이도 마찬가지로 리스트 컴프리헨션을 이용해 짧게 줄일 수 있습니다.

이중 for문의 경우에는 리스트에 for문을 여러번 넣기만 하면 됩니다. (for문은 이론상 무한번도 넣을 수 있습니다.)

물론 너무 복잡한 for문을 리스트 컴프리헨션으로 줄였다간 가독성을 개나 줘버린 코드가 되버릴테니 비교적 간단한 for문에만 사용하는 걸 권장합니다.

gugudan = [i*j for i in range(2, 10) for j in range(1, 10)]
print(gugudan)

 

이를 통해 파이썬에서 이차원 배열 역할을 하는 이차원 리스트도 만들 수 있습니다.

arr = [[0 for i in range(3)] for j in range(5)]
print(arr)
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

 

이 정도면 리스트 컴프리헨션에 대해 어느 정도 알게 된 것 같습니다.


if문 한 줄로 쓰기

파이썬에는 for문 말고도 정말 자주 쓰는데 여러 줄을 차지하는 녀석이 하나 더 있습니다. 바로 앞서 공부한 if문입니다.

if문 또한 한 줄로 처리할 수 있는 구문이 있었기 때문에 이도 소개해보려 합니다.

 

예를 들어, 입력받은 수가 홀수면 odd, 짝수면 eve를 출력하게 해보겠습니다.

일반적인 if문은 코드를 여러 줄 써야합니다.

n = int(input())

if n % 2 == 1 :
  print("odd")
else :
  print("eve")

 

그러나 이도 한 줄의 코드로 압축이 가능합니다.

print를 한다고 가정했을 때 사용법은 다음과 같습니다.

print("출력1" if 조건 else "출력2")

만약 조건이 참이라면 '출력 1'을 출력하고 아니라면 '출력 2'를 출력합니다.

n = int(input())
print("odd" if n % 2 == 1 else "eve")

 

물론 elif가 들어간 식도 줄일 수 있습니다.

print("출력1" if 조건1 else "출력2" if 조건2 else "출력3")

뭔가 느낌상 'elif 조건' 뒤에 출력문이 올 것 같은데 else와 if 사이에 출력문이 온다는 게 좀 특이하네요.

 

이렇게 if문 한 줄로 쓰는 법도 알아봤습니다. 확실히 for문에 비해 사용하는 범위도 국한된 것 같고..? 딱히 쓸 일도 없어보이긴 하지만 알아는 두면 좋을 것 같네요. (그냥 if문 쓰는 게 편할 것 같은...)


for문 + if문 한 줄로 쓰기

드디어 마지막입니다. for문과 if문이 동시에 있는 코드를 줄여서 쓰는건데, 리스트 컴프리헨션 뒤에 if문만 추가한 거라고 생각하심 됩니다.

 

이번에도 간단한 예시를 들어보겠습니다. 아래 코드는 일반적인 for문과 if문을 사용한 코드입니다.

odd_eve = []

for i in range(10) :
  if i % 2 == 1 :
    odd_eve.append('odd')
  else :
    odd_eve.append('eve')

print(odd_eve)
['eve', 'odd', 'eve', 'odd', 'eve', 'odd', 'eve', 'odd', 'eve', 'odd']

 

이제 이를 한 줄로 줄여보겠습니다.

사용법은 다음과 같습니다.

 

  • if만 사용할 경우
[표현식 for 아이템 in 이터러블 if 조건]

이 경우 if는 필터링의 역할을 합니다. for문 뒤에 써야하며, 만약 요소(아이템)가 조건에 맞는다면 리스트에 포함시킵니다.

 

ex) 0부터 9까지 중 홀수만 출력

print([i for i in range(10) if i % 2 == 1])
[1, 3, 5, 7, 9]

 

  • if ~ else를 사용할 경우
[표현식1 if 조건 else 표현식2 for 아이템 in 이터러블]

이 경우에 if else는 값을 결정하는 역할을 합니다. for문 앞에 써야하며, 조건에 맞는다면 표현식1을 리스트에 추가하고 조건에 맞지 않는다면 표현식2를 추가합니다.

 

ex) 0부터 9까지 중 홀수는 그대로, 짝수는 0으로 출력

print([i if i % 2 == 1 else 0 for i in range(10)])
[0, 1, 0, 3, 0, 5, 0, 7, 0, 9]

 

  • if ~ elif ~ else를 사용할 경우
[표현식1 if 조건1 else 표현식2 if 조건2 else 표현식3 for 아이템 in 이터러블]

아까 리스트 컴프리헨션에서 elif 사용한 거랑 비슷합니다. if와 else 사이에 조건을 넣으면 됩니다.

 

ex) 0부터 9까지 중 3보다 작으면 0, 6보다 작으면 1, 나머지는 2 출력

print([0 if i < 3 else 1 if i < 6 else 2 for i in range(10)])
[0, 0, 0, 1, 1, 1, 2, 2, 2, 2]

주의사항

이렇게 지금까지 for문과 if문을 한 줄로 줄여 쓰는 법에 대해 공부해봤습니다. 이렇게 코드를 줄여쓰면 코드 길이도 짧아지고 불필요하게 많이 쓸 필요가 없어진다는 장점이 존재하긴 합니다.

 

그러나, 너무 무분별하게 코드를 줄여쓰면 다음과 같은 참사가 날 수 있습니다.

num_a = [i*j for i in range(5) if i > 2 for j in range(4) if j >= 1]
print(num_a)
num_b = []
for i in range(5) :
  if i > 2 : 
    for j in range(4) :
      if j >= 1 :
        num_b.append(i*j)

print(num_b)

위 두 코드의 실행결과는 같습니다. 그러나, 한 눈에 직관적으로 이해하기 쉬운 건 누가 봐도 아래 코드죠. 이렇게 for문과 if문이 좀만 복잡해져도 컴프리헨션을 쓰면 너무 가독성이 떨어집니다. (물론 있어보이긴 합니다.) 

 

그러니 컴프리헨션은 정말정말 단순할 때 아니면 쓰지 않는 것이 좋습니다.


오늘은 if문과 for문에 대해 공부해봤습니다. 정말 할 게 없을 줄 알았는데 생각보다 if문과 for문을 한 줄로 줄이는 부분에 소개할게 많아 분량이 갑자기 증가했네요. 오늘 배운 리스트 컴프리헨션은 나중에 굉장히 요긴하게 사용할 수 있으니 잘 알아둬야 할 것 같습니다. (있어보이는 척도 가능)