2012년 12월 10일 월요일

[Python] Nested 문법?

개인적으로 Python 언어로 코딩을 하면서 자주 안쓰게 되는 문법이 있다. 이 문법을 정확히 어떤 용어로 표현해야 하는지 몰라서 일단 'Nested 문법' 이라고 적었는데 틀린 표현 같지만 제목이 필요하기에 어거지로 썼다.

C에 익숙했던 (비영어권) 사람이라면 아마도 Python이나 기타 스크립트 언어들 특유의 문법에 간혹 놀라기도 혹은 질리기도 한다. 스크립트 언어들의 독특한 문법 중 하나는 프로그래밍 언어를 마치 사람의 언어처럼 표현하기도 하거나 이 코드의 내용을 마구 줄여버리는 것이다.

참고로 이 글은 Python을 어느 정도 공부한 사람이라면 읽을 필요가 없다.

C에서 자주 사용했던 단축(?) 문법이라면 으례 '?'가 떠오른다. 이를 테면 이런 식이다.
void f(BOOL v) {
    printf("%s\n", v ? "YES" : "NO");
}
C의 '?' 문법은 if 문을 축약해서 사용 할 수 있게 해 준다. '?' 앞의 식이 True(0 혹은 NULL이 아니라면)이면 콜론(:) 왼쪽의 것이, False라면 콜론(:) 우측의 값이 전달된다.

하지만 Python에서는 if문을 그대로 이용한다.
>>> def f(v): print 'YES' if v else 'NO'
... 
>>> f(True)
YES
>>> f(False)
NO
만약 영어권 사람이라면 이 문장을 이해하는건 별로 생각 할 필요가 없을지도 모른다. 하지만 내가 비영어권 사람이라서 그런지 아니면 성격이 특이해서인지 아니면 C스타일을 좋아하는 건지 모르겠지만, 이런 문법은 왠지 가독성이 떨어져 보인다. 적어도 '?'를 이용하는 문법은 뭔가 체계적으로 표현하고자 하는게 나누어져 있지만 Python 방식은 글자의 순서를 머리 속에서 재배치 하지 않는 한 무슨 말인지 바로 알기는 힘들지도 모른다.

영어에 익숙하지 않다는 것이 바로 탄로나는 예제였다. 하지만 난 한국인이라서 영어를 잘 모른다는 것에 부끄럽지는 않다! :-(

Python에서는 다양한 자료구조가 기본적으로(Built-in) 지원된다. 리스트(list)라던가 사전(dict) 등등 다양하다. 이 리스트나 사전을 생성 할 때 for 문을 삽입(?)시켜서 다이나믹(?) 하게 생성하는 방법이 있다.
>>> [x*2 for x in range(1, 10)]
[2, 4, 6, 8, 10, 12, 14, 16, 18]
이 문법이 바로 와 닿는가? 미국이나 영국 출신이라면 다르게 느낄까? 적어도 난 이 문법을 처음 봤을 때 이해 할 수 없었다. 물론 기본 문법 메커니즘을 알게 되면 쉽게 이해가 되긴 한다.

리스트 안에서 for 문을 사용했다. 그런데 그 전에 알 수 없는 변수 이름(x)을 하나 던져줬다. for문에서는 이 변수(x)를 이용해 루프를 돈다. 그런데 신기하게도 이 for 루프의 내용을 바탕으로 리스트가 생성된다.

이런 문법의 이해에는 그저 제일 앞의 알 수 없는 변수 이름에 주목하면 된다. 그 이후는 이 알 수 없는 변수 이름의 데이터를 생성하는 일종의 조건/제어문이 등장한다.
l = []
for x in range(1, 10):
    l.append(x*2)
풀어쓰면 이렇다는 것이다. 그런데, 솔직히 아직도 이런 구태적인 방식이 더 이해가 잘 된다. 물론 코드양에서 비교한다면 차이가 많이 난다.

비슷한 예는 사전(dict)에서도 찾을 수 있다.
>>> { x: str(x) for x in [1, 2, 3] }
{1: '1', 2: '2', 3: '3'}
이번에도 알 수 없는 이름을 툭 던져주고 이 후 루프 제어문(for)이 등장한다. 앞의 풀어쓰기 내용을 의식했다면 뭐 굳이 풀어쓰지 않아도 이해할 수는 있을 것이다.

이 외의 독특한 문법이라면 lambda가 있겠다. 함수형(Functional) 언어에서나 볼 수 있는 '변수에 간단한 함수를 만들어 넣는 식' 이라고도 볼 수 있는데, 이건 내가 아직 함수형 언어를 잘 모르기 때문에 하게되는 표현이다.
>>> f = lambda x: str(x)*3
>>> f('1')
'111'
정말 함수같이 동작한다. 그런데 이런 lambda 문법은 언제 왜 이용해야 하는지 아직은 감이 없다. 지금까지 사용해 오면서 알고 있는 모듈에서 굳이 lambda를 활용할 일은 별로 없었고 그저 함수를 정의(def)해서 써도 되었기 때문이다.

그래서 lambda를 사용하게 되는 때는 오직 한 줄 짜리 함수를 간단히 정의 할 때 뿐이었다. 예를 들어 다음과 같은 형태다.
>>> f = lambda x: str(x)*3
>>> { x: f(x) for x in ['a', 'b', 'c'] }
{'a': 'aaa', 'c': 'ccc', 'b': 'bbb'}
>>> f('1')
'111'
앞의 사전 정의 nested 루프에서 하나를 더 추가한 것 뿐이다. (사실 굳이 f를 분리해낼 필요가 없기도 하다. 그냥 어거지 예제다.)

이해가 안된다고는 했지만, 이런 표현(문법)들은 잘 알아두면 분명 유용하다. 코드량을 획기적으로 줄일 수도 있고 언어유희적(?) 표현도 가능하다.

누군가 프로그래머에게 가장 중요한 언어는 '영어'라고 하는 사람이 있었다. 틀린 말은 아니다. 거의 모든 레퍼런스가 영어 위주로 제공되기에 프로그래머에게 프로그래밍 언어가 아닌 '영어'가 중요한 건 굉장히 현실적인 이야기이다. 하지만 그 '영어'를 잘 모른다고 뛰어나지 않은 프로그래머라고는 할 수 없다. 아니, 내가 하고 싶은 말은 영어 모른다고 부끄러워 해서는 안된다는 말이다. -_-;;; 젠장!!

댓글 없음 :