본문 바로가기

파이썬 (python)

[Python 31] 코딩, 이것만 알자

 

 

 

의외로 코딩은 단순하다. 아주 전형적인 패턴이 하나 있는데, 리스트와 For 이다. 이 리스트와 For 만 잘 활용할 수 있으면 코딩은 의의로 매우 단순해 진다. 그런 의미에서, 리스트와 For 에 대해 한번 더 복습해 보는 시간을 갖도록 하자.

 

과연, Coding = List 와 For 일까?

 

○ 데이터 구조와 알고리즘은 하나의 문제에 대한 2개의 관점으로서, 서로 연관되어 있다.

 

컴퓨터학과에서 전공필수로 배우는 과목 중에 "데이터구조와 알고리즘" 이라는 수업이 있다. 이것은, 알고리즘은 별개로 독립되어 있는 것이 아니라, 그 알고리즘에서 다루어지는 데이터가 어떤 구조로 만들어져 있는가에 따라 달라진다는 뜻이다. 즉, 데이터 구조가 달라지면, 알고리즘도 달라지게 된다는 의미이다. 내가 다룰 데이터가 리스트에 저장되어 있는 경우와 딕셔너리에 저장되어 있는 경우, 내가 원하는 결과를 찾아내기 위한 절차는 다소 달라질 수 있다. 

 

하지만, 실제 문제에서는 (물론 닭이 먼저냐, 달걀이 먼저냐의 문제일 수도 있지만...) 어떤 문제를 해결하기 위한 알고리즘이 있을 때, 그 알고리즘을 실행하는데 가장 적합한(효과적인) 데이터 구조가 무엇인지를, 그리고 그러한 데이터 구조를 어떻게 구현할 수 있는지를 고민하게 되는 것이 보다 일반적이다.

 

어쨌든, 데이터구조와 알고리즘은 땔래야 땔 수 없는 관계이고, 우리가 해결하려고 하는 문제를 구성하는 2개의 큰 관점(view point) 을 구성하게 된다. 소위, 시스템 분석 및 설계 (System Analysis and Design)에서 데이터적 관점과 프로세스적 관점의 분해와 연관되는 이야기이기도 하다. 이것도, 다음에 기회가 되면 조금 얘기를 해 보자.

 

우리에게 복잡한 문제가 주어졌다. 그 문제를 해결하기 위한 절차를 만들고자 한다. 당연히, 그 절차는 복잡할 수 밖에 없다. (가끔, 복잡한 문제를 남들보다 쉽고 간단하게 풀 수 있는 새로운 방법을 만들어 냄으로써 명성과 재물을 얻는 경우를 보게 되는데 "미래의 나" 일 수도 있음이다.)

 

○ List 와 For

 

우리가 실제로 다루는 모든 문제들은 여러 데이터를 사용한다. 여러 데이터를 가장 효과적으로 저장할 수 있는 데이터 구조는 리스트(List) 이다. 물론, 다음에 데이터프레임(Data Frame), 그래프(Graph), 트리(Tree) 등의 조금 복잡한 데이터 구조를 공부할 기회가 있겠지만, 그런 복잡한 데이터 구조들도 결국은 리스트를 터잡아 만들어졌음을 알게 될 것이다. 우리가 이미 여러차례 리스트를 다루어 보았듯이, 파이썬에서는 아래와 같은 간단한 선언으로 리스트를 만들 수 있다. 

 

 

여러개의 데이터가 한데 모여 있다. 여러개의 데이터를 하나의 묶기 위해서 중괄호( [ .... ] )가 사용되고 있다. 중괄호를 이용해서 한데 묶인 데이터들을 구별하기 위해 콤마( , ) 가 사용되고 있다. 

 

이와 같이 간단한 2개의 장치인 중괄호와 콤마를 이용해서 리스트를 선언하고 나면, 아래와 같이 리스트의 이름 만으로 데이터 전체를 가리킬 수 있다. 아래의 print(a) 라는 명령어를 우리 말로 해석해 보면 무엇이 되는가? "a 를 출력하시오" 이다. 저 많은 데이터를 우리는 단순하게 "a 를~" 이라고 가리킬 수 있게 되는 것이다.

 

 

또 하나, 리스트의 이름과 첨자(index)를 이용해서 리스트를 구성하는 각 데이터에 대한 참조가 가능하다는 것이다. 아래의 명령어에서 사용된 a[2] 란 a 리스트의 3번째 데이터를 가리키는 이름이 된다. 리스트의 인덱스는 0부터 시작하는 것을 다시 한번 돌이켜 보자.

 

 

리스트의 경우에는 튜플과 다르게 데이터를 수정할 수 있다. (이를 mutable 하다라고 표현한다.) 리스트를 구성하는 각각의 데이터는 아래와 같은 방식으로 변경할 수 있다.

 

 

그런데, 우리가 여러개의 데이터를 처리할 때에는, 각 데이터에 대해 어떤 연산을 반복해서 적용하게 되어 있다. 즉, 각 데이터에 어떤 연산들이 반복해서 이루어진다. 즉, 여러개의 데이터는 리스트에 저장되어 있고, 리스트의 각 데이터를 반복해서 처리하기 위해 for 문을 활용한다는 것이다. 가장 간단한 형태로 아래와 같은 구조가 된다. 

 

 

In[6]의 for 문을 우리 말로 해석해 보면, "a 리스트에 저장되어 있는 각 데이터 x 에 대하여" 라는 의미가 된다. 결국 for 문의 콜론( : ) 뒤에는 "그 데이터 x 를" 어떻게 처리하고 연산하는지에 대한 명령어가 따라오면 되겠다. 

 

물론, 조금 더 복잡한 문제에서는 "리스트에 저장된 데이터들 중에서 (이러이러한) 조건을 만족하는 데이터에 대해서만" 연산을  수행하는 형태도 가능하겠다. 조건을 나타내는 if 가 같이 묶이는 형태가 된다. 다음과 같은 구조를 생각해 볼 수 있겠다.

 

 

사실, 이 간단한 코드에 모든 것이 다 들어가 있다. 리스트 데이터 구조가 있고, 각 데이터를 반복해서 참조하기 위한 for 가 있고, 데이터를 선별하기 위한 if 가 있다. 

 

 

○ 설마 이렇게 간단한걸까?

 

위에서 보았던 가장 기본적 형태를 확장하고 변환하면 다양한 형태로 활용이 가능하다. 

 

먼저, 일반적인 문제에서는 리스트의 데이터들이 고정되어 있지 않다. 리스트의 크기도 변하고, 내부 데이터들도 변한다. 이를 위해 떠올릴 수 있는 것이 리스트의 메쏘드인 append( ), pop( ) 이다. append( ) 함수를 이용해서 데이터를 추가하고 pop( ) 함수를 이용해서 데이터를 삭제할 수 있다. 아래의 간단한 예제를 참고하자. 

 

먼저, for 문을 활용해서 리스트에 데이터를 저장하는 예제이다. 

 

 

다음으로, 불필요한 데이터를 pop 하여 삭제하는 예제이다.

 

 

조금 복잡한 데이터의 경우에는 각 데이터가 내부적으로 구조를 갖는 경우가 있다. 예를 들어서 하나의 데이터가 한 사람의 연락처라고 한다면, 하나의 데이터는 다음과 같이 표현될 수도 있겠다.

 

 

만약에 이런 데이터들이 여러개 있다면, 이러한 데이터들로 만들어진 리스트를 생각할 수 있겠다. 일종의 리스트의 리스트 (list of lists) 인 셈이다.

 

 

당연히 for 문을 활용해 각 데이터에 대해 접근할 수 있다. 아래의 예제를 보자.

 

 

각 데이터를 참조할 수 있다는 것은 그 데이터에 새로운 값을 저장할 수 있다는 뜻이 된다. 그 새로운 값을 구하는 함수를 우리가 개발한다면 결국 다음과 같은 형태의 코드를 만들 수 있을 것이다. 

 

 

코딩의 가장 핵심은 바인딩(binding) 이다. 어떤 변수에 값을 저장하는 것을 바인딩이라고 부른다. 

 

코딩은 데이터를 처리하여 새로운 데이터를 찾아내는 과정이다. 결국 그 과정에는 수업이 많은 바인딩이 이루어진다. a = 9 처럼 쉬운 코드일 수도 있을 것이고, a = 9*2+3 처럼 어떤 연산의 값일 수도 있고, a = b*2 처럼 다른 변수의 값을 이용해서 계산되는 형태일 수도 있다. 복잡한 연산인 경우 아예 하나의 함수로 만들어 a = f(b, c) 처럼 선언할 수도 있을 것이다. 그런데, 이 데이터들은 한 두개가 아니니, 리스트 데이터구조에 저장되어 있을 것이고, 이러한 바인딩들이 계속 반복되어야 하다보니 FOR 가 필요한 것이고, 일부의 데이터에 대해서만 연산이 이루어져야 한다면 IF 를 함께 활용하는 구조가 될 것이다. 

 

 

○ 코딩은 정말 단순한 것이다

 

위에서 살펴본 것 처럼, 코딩은 바인딩, 리스트, FOR, IF 등의 4개 단어로 충분히 설명할 수 있는 것이다. 그런데, 리스트와 for를 이해하고 나면, 코딩은 결국 바인딩(binding, assignment) 만 남는다. 정말, a = 1 의 의미만 이해하면 코딩은 끝이다. 코딩은 정말 쉽고 단순한 것이다. 물론, 첫걸음은 리스트와 FOR 이다.