☜ 제 01 장 파이썬 설치 """ Dive Into Python """
다이빙 파이썬
제 03 장 고유 데이터 유형 ☞

제 2 장 첫 번째 파이썬 프로그램

아시다시피 다른 책에서는 프로그래밍의 기본을 자꾸 반복하다가 마침내 완벽하게 작동하는 프로그램을 구축하는 것으로 공부를 끝냅니다. 그 모든 과정을 생략하겠습니다.

2.1. 뛰어 들기

다음은 완전하게 작동하는 파이썬 프로그램입니다.

아마 전혀 이해가 되지 않을 겁니다. 한줄 한줄 분해해 볼 테니 걱정하지 마세요. 그러나 먼저 잘 살펴보고 이해할 수 있는 것이 있는지 알아봅시다.

예제 2.1. odbchelper.py

아직 그렇게 하지 못 했다면 이 책에서 사용된 예제를 내려 받을 수 있습니다.

def buildConnectionString(params):
    """매개변수 사전으로부터 접속 문자열을 구축한다.

    문자열을 돌려준다."""
    return ";".join(["%s=%s" % (k, v) for k, v in params.items()])

if __name__ == "__main__":
    myParams = {"server":"mpilgrim", \
                "database":"master", \
                "uid":"sa", \
                "pwd":"secret" \
                }
    print buildConnectionString(myParams)

이제 이 프로그램을 실행해서 무슨 일이 일어나는지 살펴 보겠습니다.

윈도우즈의 ActivePython IDE라면 편집중인 파이썬 프로그램을 실행할 수 있는데 File->Run... (Ctrl-R)을 선택하면 됩니다. 출력결과는 상호대화 창에 표시됩니다.
Mac OS파이썬 IDE라면 Python->Run window... (Cmd-R)로 파이썬 프로그램을 실행할 수 있지만, 먼저 설정해야할 중요한 옵션이 있습니다. IDE에서, .py 파일을 열고 창의 오른쪽-위 모서리에 있는 까만 삼각형을 클릭해서 옵션 메뉴를 뛰웁니다. 그리고 Run as __main__ 옵션에 체크 표시가 되어 있는지 확인합니다. 파일마다 설정해야 하지만, 파일당 한 번만 설정하면 됩니다.
UNIX-호환 시스템이라면 (Mac OS X를 포함하여), 명령어 줄에서 파이썬 프로그램을 실행할 수 있습니다: python odbchelper.py

odbchelper.py의 출력결과는 다음과 같이 보입니다:

server=mpilgrim;uid=sa;database=master;pwd=secret

2.2. 함수 선언

파이썬도 다른 대부분의 언어처럼 함수가 있지만, C++처럼 따로 머리부 파일이나 파스칼(Pascal)처럼 따로 인터페이스 구현(interface/implementation) 섹션이 없습니다. 함수가 필요하면 그냥 다음과 같이 선언하면 됩니다:

def buildConnectionString(params):

주의할 것은 키워드 def가 함수 선언을 시작하고, 다음에 그의 함수 이름이 오고, 그 다음 괄호 안에 인자가 온다는 것입니다. 여러 인자라면 쉼표(commas)로 분리됩니다 (이는 나중에 보여 드리겠습니다).

또 주목할 것은 함수가 반환 데이터유형을 정의하지 않는다는 것입니다. 파이썬 함수는 반환 값의 데이터유형을 지정하지 않습니다; 심지어 반환값을 돌려줄지 말지도 지정하지 않습니다. 사실, 모든 파이썬 함수는 반환값을 돌려줍니다; 함수가 return 서술문을 실행하기만 하면 그 값이 반환됩니다. 그렇지 않으면 파이썬의 널(null) 값인 None이 반환됩니다.

비주얼 베이직이라면 (값을 돌려주는) 함수는 function으로 시작하고, (값을 돌려주지 않는) 서브루틴은 sub로 시작합니다. 파이썬에는 서브루틴이 없습니다. 모든 것이 함수이고, 모든 함수는 값을 돌려줍니다 (하다 못해 None이라도 돌려줍니다). 모든 함수는 def로 시작합니다.

params 인자는 데이터 유형을 지정하지 않습니다. 파이썬에서 변수는 명시적으로 유형이 정의되지 않습니다. 파이썬은 한 변수가 어떤 유형인지 짐작하고 그것을 내부적으로 추적 유지합니다.

자바C++ 그리고 기타 정적으로-유형정의 되는 언어에서는 함수의 반환 값과 각 함수 인자의 데이터 유형을 지정해야 합니다. 파이썬에서는 무엇이든 데이터유형을 명시적으로 지정하지 않습니다. 어떤 값을 할당하는가에 따라, 파이썬은 그 데이터유형을 내부적으로 추적유지합니다.

2.2.1. 파이썬의 데이터 유형은 다른 프로그래밍 언어와 어떻게 비교되는가

박학다식한 독자 한 분이 저에게 이런 설명을 보내 주셨습니다. 어떻게 파이썬이 다른 언어와 비교되는가:

정적으로 유형이 정의되는 언어
유형이 컴파일 시간에 고정되는 언어. 대부분의 정적 유형정의 언어는 이것을 강요한다. 모든 변수는 사용하기 전에 먼저 데이터유형을 선언해야 한다. 자바C는 정적으로 유형이 정의되는 언어이다.
동적으로 유형이 정의되는 언어
어떤 유형인지 실행 시간에 드러나는 언어; 정적인 유형정의의 반대이다. VBScript파이썬은 동적으로 유형이 정의된다. 왜냐하면 변수에 처음으로 값을 할당할 때 어떤 유형인지 짐작하기 때문이다.
강력하게 유형이 정의되는 언어
유형이 언제나 강요되는 언어. 자바파이썬은 강력하게 유형이 정의된다. 정수가 하나 있다면 그것을 명시적으로 변환하지 않고서는 문자열처럼 취급할 수 없다.
유약하게 유형이 정의되는 언어
유형을 무시해도 좋은 언어; 강력하게 유형이 정의되는 언어와 반대이다. VBScript는 약하게 유형이 정의된다. VBScript에서는 문자열 '12'와 정수 3을 결합하여 문자열 '123'을 얻어서, 그것을 정수 123으로 취급할 수 있는데, 이 모든 것이 명시적인 변환이 필요없다.

그래서 파이썬은 (명시적으로 데이터유형을 선언하지 않기 때문에) 동적으로 유형이 정의되고 (변수가 일단 데이터유형을 가지면 정말 중요하기 때문에) 강력하게 유형이 정의됩니다.

2.3. 함수 문서화하기

파이썬 함수를 문서화하려면 그 함수에 문서화 문자열(doc string)을 주면 됩니다.

예제 2.2. buildConnectionString 함수의 문서화 문자열(doc string) 정의하기

def buildConnectionString(params):
    """매개변수 사전으로부터 접속 문자열을 구축한다.

    문자열을 돌려준다."""

삼중 따옴표는 여러-줄 문자열입니다. 행갈이 문자(carriage returns) 기타 따옴표 문자들을 비롯하여, 시작 따옴표와 끝 따옴표 사이의 모든 것은 한 문자열에 포함됩니다. 어느 곳에도 삼중 따옴표를 사용할 수 있지만, 보통은 문서화 문자열(doc string)을 정의하는데 사용됩니다.

삼중 따옴표는 또 홑따옴표와 겹따옴표를 모두 가진 문자열을 쉽게 정의하는 방법이기도 합니다. 예를 들어 펄(Perl)에서의 qq/.../과 비슷합니다.

삼중 따옴표 사이의 모든 것은 그 함수의 문서화 문자열(doc string)입니다. 문서화 문자열은 그 함수가 무슨 일을 하는지 문서화합니다. 문서화 문자열(doc string)이 존재한다면 반드시 함수에서 첫 번째로 정의된 것입니다 (다시 말해, 쌍점 다음에 제일 처음 것입니다). 기술적으로 함수에 문서화 문자열(doc string)을 줄 필요는 없지만, 언제나 주는 것이 바람직합니다. 프로그래밍 수업시간마다 귀가 따갑게 들었을 줄 알지만, 파이썬에서는 그렇게 해야할 동기가 있습니다: 문서화 문자열(doc string)은 실행시간에 그 함수의 속성으로 사용할 수 있기 때문입니다.

많은 파이썬 IDE는 문서화 문자열(doc string)을 사용하여 정황-감지 문서를 제공합니다. 그래서 함수의 이름을 타자할 때, 그의 문서화 문자열(doc string)이 풍선도움말로 나타납니다. 이것은 대단히 도움이 되지만, 문서화 문자열(doc string)을 작성해 두었을 경우에만 그렇습니다.

문서화 기능에 대하여 더 읽어야 할 것

2.4. 어느 것이나 객체다

혹 잊어 버리셨을까봐 다시 언급합니다. 방금 파이썬 함수는 속성이 있고, 그 속성들은 실행시간에 얻을 수 있다고 말했습니다.

파이썬에서 다른 어떤 것과 마찬가지로 함수도 객체입니다.

애용하는 파이썬 IDE를 열고 다음을 따라해 보세요:

예제 2.3. buildConnectionString 함수의 doc string에 접근하기

>>> import odbchelper                              
>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
>>> print odbchelper.buildConnectionString(params) 
server=mpilgrim;uid=sa;database=master;pwd=secret
>>> print odbchelper.buildConnectionString.__doc__ 
Build a connection string from a dictionary

Returns string.
첫 줄에서 odbchelper 프로그램을 모듈로 반입합니다 -- 모듈은 상호대화적으로 사용할 수 있는 코드 조각 또는 더 큰 파이썬 프로그램에서 사용할 수 있는 코드 조각입니다 (제 4 장에서 여러-모듈로 구성된 파이썬 프로그램의 예를 보여줍니다.) 모듈을 반입하고 나면 그의 공개 함수와 클래스 또는 속성을 참조할 수 있습니다. 모듈은 이렇게 하여 다른 모듈의 기능에 접근할 수 있으며, IDE에서도 이렇게 할 수 있습니다. 이것은 중요한 개념이며, 나중에 좀 더 자세히 말씀드리겠습니다.
반입된 모듈에 정의된 함수를 사용하고 싶다면 그 모듈의 이름을 포함시켜야 합니다. 그래서 그냥 buildConnectionString이라고 말하면 안되고; 반드시 odbchelper.buildConnectionString라고 말해야 합니다. 자바에서 클래스를 사용해 보셨다면 이것이 좀 눈에 익으리라 봅니다.
예상하시는 것처럼 함수를 호출하는 대신에, 그 함수의 속성중 하나인 __doc__을 요청했습니다.
파이썬에서 import는 펄(Perl)의 require와 비슷합니다. 파이썬 모듈을 반입(import)하고 나면 module.function의 형태로 함수에 접근할 수 있습니다; 펄(Perl)에서 한 모듈을 요구(require)하고 나면 module::function의 형태로 함수에 접근할 수 있습니다.

2.4.1. 반입 검색 경로

앞으로 더 나아가기 전에, 간략하게 라이브러리 검색 경로를 언급하고 싶습니다. 파이썬은 모듈을 반입하고자 할 때 여러 곳을 들여다 봅니다. 구체적으로, sys.path에 정의된 디렉토리를 모두 들여다 봅니다. sys.path는 그냥 리스트입니다. 표준 리스트 메쏘드로 쉽게 볼 수 있고 수정할 수 있습니다 (리스트에 관해서는 이 장의 후반부에서 배웁니다.)

예제 2.4. 반입 탐색 경로

>>> import sys                 
>>> sys.path                   
['', '/usr/local/lib/python2.2', '/usr/local/lib/python2.2/plat-linux2', 
'/usr/local/lib/python2.2/lib-dynload', '/usr/local/lib/python2.2/site-packages', 
'/usr/local/lib/python2.2/site-packages/PIL', '/usr/local/lib/python2.2/site-packages/piddle']
>>> sys                        
<module 'sys' (built-in)>
>>> sys.path.append('/my/new/path') 
sys 모듈을 반입하면 그의 모든 함수와 속성을 얻을 수 있습니다.
sys.path는 현재 검색 경로를 구성하는 디렉토리 이름들로 이루어진 리스트입니다 (운영 체제에 따라서, 어느 버전의 파이썬을 실행중인지 그리고 처음에 어디에서 설치되었는지에 따라서 다르게 보일 것입니다.) 파이썬은 이런 디렉토리들을 (이 순서대로) 조사해서 반입하고자 하는 모듈 이름에 일치하는 .py 파일을 찾습니다.
사실, 거짓말을 했습니다; 진실은 그 보다 더 복잡합니다. 왜냐하면 모든 모듈은 .py 파일에 저장됩니다. sys 모듈 같이 어떤 것은 "내장 모듈 입니다"; 내장 모듈은 실제로 파이썬 그 자체에 바로 구워 넣은 모듈입니다. 내장 모듈은 일반 모듈과 똑 같이 행위하지만, 파이썬 소스 코드가 없습니다. 왜냐하면 파이썬으로 작성된 것이 아니기 때문입니다! (sys 모듈은 C로 작성되었습니다.)
새로운 디렉토리를 실행시간에 파이썬의 검색 경로에 추가할 수 있습니다. 디렉토리 이름을 sys.path에 추가하면 모듈을 반입할 때마다 파이썬은 그 디렉토리를 찾습니다. 그 효과는 파이썬이 실행중인 동안 지속됩니다. (append와 기타 리스트 메쏘드에 관해서는 제 3 장에서 자세하게 다룹니다.)

2.4.2. 객체란 무엇인가?

파이썬에서는 무엇이든 객체이며, 거의 모두 속성과 메쏘드가 있습니다. 모든 함수는 내장 속성 __doc__이 있는데, 이 속성은 함수의 소스 코드에 정의된 문서화 문자열(doc string)입니다. sys 모듈은 (무엇보다도) path라고 부르는 속성이 있는 객체입니다. 등등.

여전히, 의문이 남습니다. 객체란 무엇인가? 프로그래밍 언어마다 서로 다르게 “객체(object)”를 정의합니다. 어떤 언어에서는 모든 객체가 반드시 속성과 메쏘드를 지녀야 한다는 뜻이지만; 또 다른 언어에서는 모든 객체가 하부클래스화가 가능하다는 뜻입니다. 파이썬에서는 좀 느슨하게 정의합니다; 어떤 객체는 속성이나 메쏘드도 없으며 (이에 관해서는 제 3 장에서 자세히 다룸), 모든 객체가 하부클래스화가 가능한 것도 아닙니다 (이에 관해서는 제 5 장에서 자세히 다룸). 그러나 무엇이든 변수에 할당이 가능하고 함수에 인자로 건넬 수 있다는 점에서 객체입니다 (이에 관해서는 제 4 장에서 자세히 다룸).

이것은 너무나 중요해서 혹시라도 잊지 않으시도록 몇 번이라도 반복해서 상기시켜 드리겠습니다: 파이썬에서는 무엇이든 객체입니다. 문자열도 객체이며 리스트도 객체이고 함수도 객체입니다. 심지어 모듈도 객체입니다.

객체에 관하여 더 읽을 것

2.5. 코드 들여쓰기

파이썬 함수는 함수 코드가 시작하고 멈추는 위치를 표식하는 begin이나 end가 명시적으로 없으며, 괄호도 없습니다. 유일한 구분자는 쌍점(:)과 코드 그 자체를 들여쓰는 것입니다.

예제 2.5. buildConnectionString 함수 들여쓰기

def buildConnectionString(params):
    """Build a connection string from a dictionary of parameters.

    Returns string."""
    return ";".join(["%s=%s" % (k, v) for k, v in params.items()])

코드 블록은 들여쓰기로 정의됩니다. "코드 블록"이란 함수, if 서술문, for 회돌이, while 회돌이, 등등을 뜻합니다. 들여쓰면 블록이 시작되고 내어쓰면 블록이 끝납니다. 명시적으로 반괄호나 각괄호 또는 키워드가 없습니다. 다시 말해 공백이 중요하며 일관성이 있어야 한다는 뜻입니다. 이 예제에서 (문서화 문자열을 포함하여) 함수 코드는 네 개의 공간문자만큼 들여쓰기 되어 있습니다. 꼭 공간문자가 네 개일 필요는 없습니다. 그저 일관성만 있으면 됩니다. 들여쓰기 되어 있지 않은 첫 줄은 함수의 바깥입니다.

예제 2.6, “if 서술문”if 서술문에 사용되는 코드 들여 쓰기의 예를 보여줍니다.

예제 2.6. if 서술문

def fib(n):                   
    print 'n =', n            
    if n > 1:                 
        return n * fib(n - 1)
    else:                     
        print 'end of the line'
        return 1
이는 fib라는 함수로서 인자를 하나 n을 취합니다. 함수 안의 모든 코드는 들여쓰기 됩니다.
화면을 인쇄하는 일은 파이썬에서 아주 쉽습니다. 그냥 print를 사용하면 됩니다. print 서술문은 어떤 데이터 유형이든 취합니다. 문자열과 정수 그리고 다음 장에서 배울 사전과 리스트 같은 기타 고유의 유형이 있습니다. 값을 쉼표로-가른 리스트를 사용하면 한 줄에 여러 가지를 섞어 맞추어서 인쇄할 수 있습니다. 각 값은 공간 문자로 분리되어 같은 줄에 인쇄됩니다 (쉼표는 인쇄되지 않습니다). 그래서 fib5로 호출되면 "n = 5"가 인쇄됩니다.
if 서술문은 코드 블록 유형입니다. if 표현식이 참으로 평가되면 들여쓰기된 블록이 실행됩니다. 그렇지 않으면 else 블록으로 실행이 옮겨갑니다.
물론 if 블록과 else 블록에는 여러 줄이 담길 수 있습니다. 같은 양만큼 들여쓰기만 되어 있으면 됩니다. 이 else 블록은 두 줄의 코드를 안에 담고 있습니다. 여러-줄 코드 블록을 위한 다른 특별한 구문은 없습니다. 그냥 들여쓰고 즐기시면 됩니다.

처음에는 포트란(Fortran)과 이리저리 비교해 보면서 저항을 하지만, 곧 이에 익숙해져서 그의 장점을 보기 시작합니다. 한 가지 큰 혜택은 모든 파이썬 프로그램이 비슷해 보인다는 것입니다. 왜냐하면 들여쓰기가 스타일의 문제가 아니라 언어의 필수조건이기 때문입니다. 이 때문에 다른 사람의 파이썬 코드를 읽기 쉽고 이해하기 쉽습니다.

파이썬은 행갈이 문자를 사용하여 서술문을 가르고 쌍점과 들여쓰기를 사용하여 코드 블록을 가릅니다. C++ 그리고 자바는 쌍반점을 사용하여 서술문을 가르고 활괄호를 사용하여 코드 블록을 가릅니다.

코드 들여쓰기에 관하여 더 읽어야 할 것

2.6. 모듈 테스트

파이썬 모듈은 객체이며 여러 유용한 속성이 있습니다. 이를 이용하면 쉽게 모듈을 작성해 가면서 테스트할 수 있습니다. 다음은 if __name__ 트릭을 사용하는 예제입니다.

if __name__ == "__main__":

몇가지 잠깐 관찰한 후에 무엇이 좋은지 알아 보겠습니다. 첫째, if 표현식 주위에 괄호가 요구되지 않습니다. 둘째, if 서술문은 쌍점으로 끝나며, 다음에 들여쓰기된 코드가 따라옵니다.

C처럼, 파이썬==를 비교에 사용하고 =를 할당에 사용합니다. C와 다르게, 파이썬은 인-라인 할당을 지원하지 않습니다. 그래서 비교하고 있다고 생각하는 값을 우발적으로 할당할 가능성은 전혀 없습니다.

그래서 왜 이 특별한 if 서술문이 트릭인가? 모듈은 객체입니다. 그리고 모든 모듈은 내장 속성으로 __name__이 있습니다. 모듈의 __name__은 모듈을 어떻게 사용하는가에 따라 다릅니다. 모듈을 반입(import)한다면 __name__은 디렉토리 경로나 파일 확장자 없이 그 모듈의 파일이름입니다. 그러나 그 모듈을 독립 프로그램으로 직접 실행할 수도 있습니다. 이런 경우 __name__은 특별한 기본 값 __main__이 됩니다.

>>> import odbchelper
>>> odbchelper.__name__
'odbchelper'

이를 이해하면 모듈 안에 이 if 서술문을 배치하여 테스트 모듬을 디자인할 수 있습니다. 모듈을 직접 실행하면 __name____main__이 되고, 그래서 테스트 모듬이 실행됩니다. 모듈로 반입하면 __name__은 다른 어떤 것이 되고, 그래서 테스트 모듬은 무시됩니다. 이렇게 하면 새로운 모듈을 좀 더 큰 프로그램 안으로 병합하기 전에 디버그하고 개발하기가 쉽습니다.

MacPython에서 if __name__ 트릭을 작동시키려면 조치가 더 필요합니다. 창의 우-상 모서리에 있는 까만색 삼각형을 클릭하여 모듈의 옵션 메뉴를 띄웁니다. 그리고 Run as __main__이 체크되어 있는지 확인합니다.

모듈 반입에 관하여 더 읽어야 할 것

☜ 제 01 장 파이썬 설치 """ Dive Into Python """
다이빙 파이썬
제 03 장 고유 데이터 유형 ☞