파이썬은 기본적으로 문자열, 리스트, 튜플, 사전을 언어 차원에서 지원할 수 있는 스크립트 언어입니다. 오늘 알아볼 유형은 문자열과 리스트입니다. 나중에는 큐와 스택의 경우 리스트 안에 이를 Emulation (흉내내기)할 수 있는 함수를 호출하는 것으로 작업이 가능함을 확인하고 좀 더 자세히 다루어보기로 하겠습니다.

참고로 파이썬은 STL이나 .NET에서처럼 Stack과 Queue라는 것이 명확하게 존재하는 것이 아니므로 주의할 점이 있겠지요. 즉, 리스트를 사용하고 있지만 리스트가 아닌 스택이나 큐로서의 역할을 하고 있음을 명확히 알려줄만한 어떤 힌트가 포함되어야 한다는 뜻입니다. 쉬운 예로 변수 이름의 정의부터 달리한다거나 주석을 달거나 하는 등의 일이 있을 것입니다.

다시 본론으로 돌아가서, 파이썬이 기본적으로 제공하는 네 가지 유형의 데이터 구조를 분석해 보도록 하겠습니다.

* 문자열 (String)

파이썬의 문자열은 우리가 아는 문자열과 90% 같습니다. 나머지 10%가 무엇일까요? 파이썬에서의 문자열은 우리가 C/C++/Java/C#에서처럼 문자열의 특정 인덱스에 있는 글자를 치환하는 것을 지원하지 않습니다. C 계열 언어를 사용하다가 제일 어렵게 느껴지게 되는 부분이 바로 이 부분일 것입니다. 또한,  파이썬 코드에서의 문자열 표기는 작은 따옴표가 문자 하나를 나타내고, 큰 따옴표가 문자열을 나타내는 것이 아닙니다. 양쪽 표기 방식 모두 문자열을 의미합니다.

* 리스트 (List)

앞에서 예를 들었던 문자열과는 달리 리스트는 원소 단위의 편집이 가능하며 서두에서 설명하였던 그대로 큐와 스택을 에뮬레이션할 수 있는 관련 함수도 제공한다고 하였습니다.

리스트를 만들기 위해서는 다음과 같이 작성할 수 있습니다.

name = [ 'young-hee', 'cheol-soo', 'joo-yeon', 'min-ji' ]
loves = [ 'young-hee', [ 'min-su', 'cheol-soo' ], 'dong-soo', [ 'min-ji', 'jinee' ] ]

loves 리스트가 독특해 보입니다. 즉, 리스트 안에 리스트를 중첩해서 삽입하는 것이 가능함을 보여주고 있습니다.

리스트는 앞서 설명한 문자열과는 달리 훨씬 유연합니다. 원소의 개별 편집을 지원하기도 합니다. 특정 원소를 지우기 위해서는 다음과 같이 명령을 내리면 됩니다.

del name[0]
del loves[0]
del loves[0][1]

리스트에 제공되는 몇 가지 함수를 알아보도록 하지요. 우선 리스트를 사용하면서 가장 많이 사용할 정렬 함수를 살펴보면 간단합니다.

name.sort()
loves.sort()

결과를 확인해보려면 간단히 변수 이름만 입력해봐도 알 수 있습니다. 그런데 loves의 경우 중첩된 리스트에 있는 것이 앞으로 오고 개별 원소만 정렬된 상태로 되어있습니다. 무엇을 의미하는 것일까요? 중첩 리스트에서의 정렬은 재귀적이지 않음을 보여주는 것입니다.

중첩 리스트를 이용하여 간단히 행렬도 표현해볼 수 있을 것입니다. 예를 들면 [[1, 2, 3], [1, 1, 1], [3, 2, 1]] 과 같다고할 수 있겠지요.

** 돌발 퀴즈: 문자열과 리스트는 서로 형식 변환이 가능한 관계입니다. 문자열을 리스트로 바꾼 것과 리스트를 문자열로 바꾼 것의 차이점을 확인해 보시고 댓글로 그 차이점을 남겨주시기 바래요. ^^

돌발 퀴즈를 위한 힌트를 하나 드리겠습니다. 리스트와 문자열 사이의 형변환은 아래와 같이 하면 됩니다.

a = list('my lover')
b = str(a)

다음 Chapter에서는 리스트에서 제공하는 큐와 스택 에뮬레이션 기능을 살펴보기로 합니다.

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

Python은 기존의 주류 언어들과 마찬가지로 함수와 객체를 지원합니다. Iron Python의 경우에도 당연히 이것이 가능합니다. 하지만 혼동하기 쉬운 점이 있는데, IronPython은 원래 "전역 (Global)"의 개념이 존재하지 않는 .NET 프레임워크의 특성을 간단히 무시하고 원래 Python의 특징을 흉내냅니다. 나중에 다룰 IronPython을 .NET Application에 Integration하는 단계에서 이것의 진짜 내막을 정확히 볼 수 있게 됩니다.

이러한 특징은 Visual Basic .NET의 모듈과 비슷한 원리인데, Visual Basic .NET의 모듈도 엄격히 따지면 보통의 클래스이지만 모듈의 이름을 애써 지정할 필요 없이 마치 전역 멤버처럼 사용하는 것이 가능한 이유가 Visual Basic 6.0의 특성을 흉내낸 것이기 때문입니다. 결론적으로 MSIL 코드에서는 전체 이름을 모두 기입해줍니다.

오늘 Chapter에서는 함수를 간단히 정의하고 사용하는 방법에 대해서 살펴보기로 합니다. 그리고 후반부에서는 C# 3.0에서도 도입이 거론되고 있는 람다에 대해서도 파이썬을 통해 보기로 합니다. 파이썬의 경우 람다는 실제로 사용하는 정규 문법입니다.

IronPython 콘솔을 켜고 다음과 같이 입력하도록 합니다.

def add(a, b):
  return a+b

구조는 너무나도 간결합니다. a와 b라는 것은 짐작이 가능합니다. 바로 함수의 매개 변수가 되는것이지요. 하지만 C#이나 VB.NET과는 달리 상당히 생략된 것이 많음을 알 수 있습니다. 하지만 이상하게 생각할 필요는 없습니다. 왜냐면, 우리는 목적에 맞는 프로그램을 온전히 구현하기 위한 것이 목표가 아니라 스크립트 언어의 특성에 맞는 프로그램을 표현 (Illustration)하기 위함이므로 이정도면 충분한 것입니다.

일단 a와 b라는 각각의 매개 변수에 대한 형식은 따로 지정하지 않았습니다. 즉 a와 b는 어떤 형식이든 대입이 가능함을 뜻합니다. 그리고 add라는 함수에 반환 형식을 지정하지 않았습니다. return 문 또는 뒤에 나올 yield 문 그 자체의 용법과 그것들이 다루는 데이터 형식에 따라서 함수의 반환 형식이 자동으로 결정될 수 있고 정확히 알 수 없는 경우에는 일반화된 형식으로 자동으로 결정하여 줄 것입니다.

위의 add 함수를 호출하는 방법 역시 간단합니다.

print add(1, 3)
print add("hello ", "world ")

첫 번째의 경우 숫자 4를 반환할 것입니다. 두 번째의 경우에도 Concatenation 처리가 된 문자열이 반환될 것입니다. 두 가지 동작 모두 유효한 것입니다.

이번에는 재귀호출을 사용하는 예를 다루어보도록 하겠습니다. 팩토리얼을 구하는 함수를 프로그래밍해보면 좋겠지요. ^^

def factorial(n):
  if n <= 1: return 1
  return n * factorial(n-1)

기본 알고리즘에 대해서는 따로 설명하지 않겠습니다. 당연한 이야기이지만 재귀 호출이 가능함을 보이고 있습니다.

이번에는 yield 키워드에 대하여 살펴보도록 하겠습니다.

def one_to_three():
  yield 1
  yield 2
  yield 3

yield 키워드는 C# 2.0의 것과 완전히 같은 용법을 제공합니다. 다만 return 키워드를 더 쓰지 않고 yield 문 하나만을 사용합니다.

그리고 함수를 프로그래밍하면서 필요한 것이 하나 더 있는데, 바로 함수의 문서화 작업입니다. 간단하지만 습관으로 두시는게 좋겠지요. Iron Python은 따로 문서화 문자열을 두지 않으면 자동으로 함수의 시그니처 (함수의 반환 형식과 매개 변수 목록, 함수의 이름과 같은 정보)를 생성하여 문서화에 반영하지만 이것을 직접 변경할 수도 있습니다.

def one_to_three_v2():
  "이곳에 설명문을 달아놓으면 됩니다."
  yield 1
  yield 2
  yield 3

첫 줄에 지정한 문자열이 바로 문서화 문자열이 됩니다. 이것을 확인해 보기 위하여 두 가지 방법을 쓸 수 있는데 하나는 __doc__ 프로퍼티를 직접 조회하는 것이고 또 하나는 help() 내장 함수를 이용하는 것입니다.

help(one_to_three_v2)
print one_to_three_v2.__doc__

help 내장 함수의 경우 좀 더 정리된 모습을 보여줍니다. 두 번째 방식도 가능한 것이므로 참고하시기 바랍니다.

오늘의 마지막 순서로 람다에 대하여 살펴보기로 합니다. 람다는 앞서 간단한 설명을 통해 언급하였듯이 C# 3.0에서 도입하고자 하는 람다와 유사한 것입니다. 람다는 한 줄에 표현이 가능한 수식을 함수로 만들어줍니다. 다음의 예를 살펴보도록 하지요.

(lambda x, y: x ** y)(10, 3)

위와 같이 구문을 입력하면 10의 3승 값인 1000이 반환됩니다. 간단히 분석해보도록 하지요. x와 y는 함수에서처럼 매개 변수를 뜻합니다. 그리고 : 기호 다음에 나오는 것이 수식이 됩니다. 람다는 값을 반환하는 작업 등은 전혀 하지 않습니다. 하지만, "평가"가 가능한 식 그 자체가 반환값이 됩니다.

일반적으로 모든 수식은 반환값이 자동으로 산출되는 "평가"가 가능한 형태입니다. 그리고 반환값이 있는 모든 종류의 함수들을 포함하여 읽기가 가능한 프로퍼티, 상수, 변수 등도 "평가"가 가능한 형태입니다. 이 두 가지를 모두 활용하더라도 반환값을 만들어낼 수 있는 것도 가능합니다. 더 나아가, 람다 자체는 어떤 값을 분명히 반환한다는 일종의 규약을 가지고 있기 때문에 람다 안에 람다를 집어넣는 중첩도 가능합니다.

람다는 저장해두었다가 필요할 때 재사용할 수 있습니다. 위의 식을 임의의 함수 o로 받아봅니다.

o = lambda x, y: x ** y
o(10, 3)

방금전과 마찬가지의 결과가 나타나게 됩니다. 이번엔 좀 더 나아가 람다 안에 람다를 집어넣는 중첩의 한 예를 보겠습니다.

(lambda x, y: (lambda z: z + 1)(x) ** y)(9, 3)

실용적으로 보이지는 않지만 가능한 예임을 들기 위하여 다소 복잡한 코드를 써보았습니다. 차례대로 따라가보면 쉽습니다. 안쪽의 람다부터 살펴보도록 하지요.

안쪽의 람다는 z라는 매개 변수를 받고 z에 1을 더하는 계산을 합니다. 함수 정의에 이어서 곧바로 호출을 하는데 여기에 들어갈 값은 바깥쪽의 람다의 x라는 매개 변수입니다. 즉, x에 1을 더한 값을 반환합니다. 그리고 이렇게 나타난 값에 y승 연산을 시키도록 합니다. 이것이 바깥 람다가 됩니다. 곧 이어, 바깥 람다 정의에 이어 호출에 들어가는데 인수로 9와 3이 주어집니다. 결과적으로 9는 1을 더하여 10이 되고 10의 3승을 계산합니다. 즉, 1000이 반환되겠지요.

오늘 강좌도 상당히 길었습니다만 도움이 되실거라 믿습니다.

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

Python은 단독으로는 사용하기에는 그 기능이 너무 빈약합니다. 하지만 다른 구현과 다른 모듈들이 결합되는 그 시점부터 Python의 기능은 매우 막강해집니다. 특히 IronPython의 경우 그렇습니다.

IronPython에서는 내장 라이브러리는 물론 다른 외부 Python 모듈이나 .NET Framework의 클래스 라이브러리 등을 import 명령으로 가져올 수 있습니다.

import sys

위의 명령을 입력하면 sys 모듈을 사용할 수 있는 상태로 준비하는 것입니다. 위와 같이 입력한 다음에 아래처럼 입력해봅시다.

print sys.getrecursionlimit()

함수 이름에서도 알 수 있듯이 위에서 제공하는 기본 함수는 IronPython이 수용할 수 있는 범위에서의 재귀 함수 호출 가능 깊이입니다. 사소한 것일 수 있지만 위와 같은 시스템 정보 관련 함수들은 IronPython을 비롯한 다양한 Python 인터프리터가 일반적인 Intel Processor 기반의 PC가 아닌 다른 PC나 장비에서 사용이 가능하기 때문에 매우 중요합니다. 즉, 어떤 면에서는 Java나 .NET보다 더 범용성이 좋은 것입니다.

sys 모듈을 통하여 알아볼 수 있는 정보들은 이외에도 매우 많습니다. 계속 살펴보도록 하죠.

# 기본 인코딩을 조사 (IronPython은 .NET Framework 개체명을 리턴할 것입니다.)

print sys.DefaultEncoding

# C API Version 조사 (IronPython에서는 안내 메시지가 대신 출력되며, CPython에서는 정확한 버전 정보가 출력됩니다.)

print sys.api_version

# 프로그램에 전달된 명령줄들이 나타납니다. 현재 버전에서는 ipy에 다른 인수를 지정할 수 없습니다. (이후에 ipy가 아닌 다른 프로그램에서 IronPython을 사용하는것이라면 가능합니다.)

print sys.argv

# 시스템이 Little Endian 체제인지 Big Endian 체제인지를 확인합니다. 요즈음 Windows 운영 체제라면 Little Endian이라고 볼 수 있겠습니다.

print sys.byteorder

# IronPython의 저작권 정보입니다.

print sys.copyright

# 다중 콘솔을 지원하는 유닉스나 리눅스와 같은 환경에서의 사용을 고려한 것으로 보이며, Windows 시스템을 기반으로 하는 IronPython의 경우 사용할 수 없습니다. (다만 메시지가 대신 출력됩니다.)

print sys.displayhook

# 마찬가지로 사용할 수 없는 정보입니다.

print sys.excepthook

# 현재 프로그램이 실행된 경로를 출력합니다. IronPython 인터프리터에서 조회하면 IronPython이 설치된 경로가 대신 나타날 것입니다.

print sys.exec_prefix

# 현재 프로그램의 실제 경로를 출력합니다. 물론 이것 역시도 IronPython 인터프리터를 통한 것이라면 인터프리터의 기준에 맞추어갑니다.

print sys.executable

# Ctrl+Z 키를 통하지 않고 종료할 수 있는 또 다른 방법은 이 함수를 호출하는 것입니다.

sys.exit()

# IronPython의 소스 코드를 한 번 살펴봐야 하겠지만 지금 이 함수는 한 가지 재미있는 예외를 발생시키는데, IronPython 내부적으로 Mark & Sweep 가비지 컬렉터를 사용한다는 이야기가 나옵니다.

o = object()
print sys.getrefcount(o)

# 아래의 필드에 관해서는 좀 더 조사해보고 A/S 해드리겠습니다.

print sys.hexversion

# 최대 범위의 정수를 조사하기 위해 사용합니다.

print sys.maxint

# 최대 범위의 유니코드 범위를 조사하기 위해 사용합니다. (Char 형 타입과 아마 관련이 있을것입니다.)

print sys.maxunicode

# 기본으로 로딩되는 모듈들의 목록을 조사합니다.

print sys.modules

# IronPython이 자동으로 검색하는 경로들의 목록을 조사합니다. Windows NT의 환경 변수의 하나인 %PATH%와는 관련성이 없습니다.

print sys.path

# IronPython의 플랫폼 정보를 출력합니다. .NET Framework를 기반으로 하고 있으므로 "cli"가 반환될 것입니다. Mono의 경우는 아직 체크해보지 못했습니다. 왜 CLI인지는 아시겠지요? Common Language Infrastructure의 약어이고 이것이 .NET Framework를 지칭하기 때문입니다.

print sys.platform

# exec_prefix와 유사한 것으로 보입니다. 구체적인 내용 역시 이후에 A/S 해드리도록 하겠습니다.

print sys.prefix

# 기본 프롬프트의 모양을 가져오거나 설정할 수 있습니다. 이것은 IronPython 인터프리터에 한정되는 내용일 것입니다.

print sys.ps1
sys.ps1 = '철뱀> '
sys.ps1 = '>>> '

# 여러줄 입력 모드 프롬프트의 모양을 가져오거나 설정할 수 있습니다. 역시 IronPython 인터프리터에 한정됩니다.

print sys.ps2
sys.ps2 = '철뱀2> '
sys.ps2 = '... '

# 표준 파일 핸들에 쉽게 접근할 수 있도록 고안된 것이며 지금의 것은 표준 오류 스트림입니다. 아래 예제는 오류 스트림에 한 줄의 문자열을 출력합니다.

sys.stderr.write('test\n')

# 표준 파일 핸들에 쉽게 접근할 수 있도록 고안된 것이며 지금의 것은 표준 입력 스트림입니다. 아래 예제는 입력 스트림으로부터 한 줄의 문자열을 읽습니다.

sys.stdin.readline()

# 표준 파일 핸들에 쉽게 접근할 수 있도록 고안된 것이며 지금의 것은 표준 출력 스트림입니다. 아래 예제는 출력 스트림에 한 줄의 문자열을 출력합니다.

sys.stdout.write('test2\n')

# IronPython의 버전 정보를 문자열로 확인합니다.

print sys.version

# IronPython의 버전 정보를 객체로 확인합니다.

print sys.version_info

각각의 예제는 한 번씩 살펴보시면 되겠습니다. 그리고 IronPython이 진정으로 의미있는 부분은 역시 .NET Framework 기반이며 자유롭게 .NET Framework를 이용할 수 있어야 한다는 점이 되겠지요. 그래서 IronPython만의 모듈이 하나 더 있는데 바로 clr 모듈입니다.

import clr

위의 모듈을 로드한 상태에서 즉시 WIndows Forms 객체를 하나 만들어보도록 합니다.

clr.AddReference("System.Windows.Forms")
import System.Windows.Forms
from System.Windows.Forms import Form
o = System.Windows.Forms.Form()
o.Text = 'Hello world in Python!'
o.ShowDialog()

하나씩 분석해보도록 하겠습니다. 우리가 방금전에 로드한 clr 모듈의 멤버 함수인 AddReference 함수를 호출하여 GAC에 장착된 System.Windows.Forms 어셈블리를 추가하였습니다. 그러고는 곧장 import 명령으로 다시 System.Windows.Forms 네임스페이스를 가져왔습니다.

여기서 착각하지 말아야 할 것은, import 명령어가 C#의 using이나 Visual Basic .NET의 Imports와 같지 않다는 점입니다. 다만 단독으로 import를 사용하는 것은 이러한 네임스페이스나 모듈의 사용을 준비하는 것을 지시하는 정도입니다.

그 다음줄을 살펴봐야 하는데, 바로 from ~ import 절입니다. from 다음에는 import로 가져올 메서드, 변수, 형식이 들어있는 네임스페이스나 모듈을 지정하고 import에서는 해당하는 이름을 넣어줍니다. 만약 해당 모듈 안의 모든것을 가져오려면 Asterisk (*) 기호를 넣으면 됩니다. 하지만 IronPython의 동작 특성이 인터프리터 기반이라는 것을 감안할 때 형식 수가 많은 .NET Framework Assembly의 모듈들에 대해서는 별로 적절하지 않을 것입니다. 그러므로 위에서와 같이 Form 형식만을 우선 가져옵니다.

이제 준비는 끝났고 실제로 객체를 생성해봅니다. IronPython이 인터프리터 방식이라는 것을 아직 잊지 않았다면 변수 선언 하는 것을 보고 놀라시면 안되겠지요. 즉, Late-Binding 스타일입니다. 스크립팅 언어의 생명력은 바로 여기에 있는것이지요. 참고로, 해묵은 성능 문제와 스크립팅 언어의 단점을 지적하는 것은 이 강의의 주제와도 맞지 않는 질문일 뿐더러 강의 주제를 잘못 고르신 것입니다. 이런 질문은 하지 말아주세요.

본론으로 돌아와서 o라는 변수에 Form 클래스의 생성자를 호출했습니다. 생성자를 호출하는 방법이 참 심플합니다. 생성자도 함수처럼 사용이 가능하지요.

이제 생성된 객체의 프로퍼티에 뭔가 값을 써 넣어보도록 합니다. Text 속성에 문자열을 집어넣었습니다. Form 클래스의 경우 Text 속성에 들어가는 것이 창의 제목 표시줄에 찍힐 문자열이 됩니다.

자, 이제 대충 의도한대로 되었으니 화면에 띄워보아야 겠습니다. ShowDialog 메서드를 호출하면 될 것입니다. 이렇게 구동하면 Modal 상태로 Dialog가 나타날 것입니다.

하지만 Show 메서드나 Visible 프로퍼티로 창을 띄우게 되면 적절한 메시지 루프가 형성되지 않기 때문에 창이 곧 얼어버리고 맙니다. 그렇긴 해도 인터프리터는 살아있겠지요. 이 때 창을 강제로 닫게 되면 인터프리터까지 같이 종료됩니다.

농담 한마디 하자면, Windows 입장에서 보았을 적에 이와 같이 메시지 루프를 제공해주지 않아서 얼어버린 창과 마찬가지로 창에 연결된 실제 프로세스도 이런 상황이 오면 응답이 없는 것으로 간주한 것입니다. 상당히 아둔한 처리 방식이라는 것을 알 수 있죠. 그렇긴 해도 대개의 경우 연결된 프로세스가 삼천포로 빠졌기 때문에 창에 관련된 메시지 루프를 끌고가지 못하기 때문에 이와 같이 처리하도록 프로그래밍했다고 볼 수 있겠습니다.

이번 Chapter는 좀 길었던것 같네요. 다음 Chapter도 기대해주세요. ^^

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

지난 Chapter에서 설명했던 반복문에 대한 보강이 될 수도 있고 range 함수에 대한 보강이 될 수도 있겠네요. 지난 Chapter의 반복문에서 뭔가 캐치하셨길 바랍니다.

제가 말하고 싶었던 것은 지난 Chapter의 반복문이 C#의 foreach, VB .NET의 For Each와 같다는 뜻이었습니다. Python에서 i라는 변수를 선언하고 in 지시자를 이용하여 range 함수가 반환한 것을 탐색하도록 했었지요. 그렇습니다. range 함수는 .NET Framework의 관점에서 보았을 때 정수형 배열을 생성해주는 Static Method 정도로 이해할 수 있겠습니다.

range 함수의 용법에 대해 오늘은 좀 더 살펴보도록 하겠습니다. 제가 지금부터 이야기하는 C 코드들을 Python 코드와 대조해보시고 변환해 보시면 유용할 것입니다.

C 언어에서 0부터 n까지 수를 증가시키며 반복하기 위해 우리는 흔히 이와 같이 코딩하였습니다. 미리 말씀드리자면 n은 다른 수로 대체하는 것이 올바르겠지요?

int i;

for(i=0; i<n; i++)
{
  // blah blah blah...
  fprintf(stdout, "%d", i);
}

위의 예제를 Python 스타일로 만들어봅니다.

for i in range(n):
  print i

range() 함수는 우리가 의도한 대로 0부터 n-1까지 반복하며 매회 그 카운트를 표준 출력 스트림에 출력하였습니다. 콘솔에 프린트할 수도 있는 것이지만 표준 출력 스트림은 얼마든지 대체가 가능한 사항이기 때문에 위의 C 스타일 코드에서도 굳이 fprintf를 선택하였습니다. (유닉스나 리눅스와 같은 OS를 조금이라도 공부해 보셨다면 아실 수 있는 내용이니까 이 정도로 해두겠습니다.)

지난 Chapter에서 설명하였던 것과 마찬가지로 range에는 세 가지 타입이 있습니다. 위에서 사용한 것은 range 함수의 기본 사용법입니다. 위의 Python 예제와 완전히 같지만 range 함수의 다른 버전을 이용하도록 변형해 보면 아래와 같습니다.

for i in range(0, n):
  print i
for i in range(0, n, 1):
  print i

두 번째를 살펴보도록 합니다. 시작점을 0으로하고 끝점을 n으로 지정하였는데, 실제로 나타나는 끝 원소는 n - 1이기 때문에 우리가 의도한 것과 같습니다. 만약 정확히 n을 지정하려 하였다면 n+1을 끝 원소로 대신 주면 됩니다. 즉, n+1-1이 끝점이므로 n이 반환되는 것입니다.

세 번째에서도 위의 두 번째 예제와 같은 의도로 처음 두 인자가 지정되었습니다. 하지만 세 번째 인자의 의미가 중요한데, 우리가 for 구문에서 제일 중요하게 여기는 사항 중의 하나인 증감 연산에 관한 사항입니다. 아쉽게도 더하거나 빼는 정도로밖에 처리가 안되지만 이곳의 값이 양수냐 음수냐에 따라서 진행방향이 달리 결정됩니다. 위의 예제에서는 양의 정수 1을 넣었으므로 숫자 1씩 양의 방향으로 증가할 것을 지시하고 있는 것입니다.

다양한 형태의 for 문을 가지고 연습해보시기 바랍니다.

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

Python은 종전에 우리가 알고 있는 언어인 C나 C++과는 다르게 중괄호를 여닫는 방식이 아니라 들여쓰기에 민감한 문법을 가지고 있습니다. 우리가 흔히 말하는 화이트 스페이스 중에서도 개행과 관련이 없는 문자여야만 합니다. 예를 들어 가로 탭 (키보드의 Tab키로 입력이 가능한 기본 8글자/4글자 크기의 탭을 말합니다.) 이나 스페이스 정도가 있겠지요. 이 점이 제일 중요하죠. 제 생각에, 파이썬을 이용해서 프로그래밍을 하다가 사람들이 흔히 겪는 문제점은 대부분 이런 차이점으로부터 나타나는 것 같습니다.

IronPython도 Python의 기본 문법을 충실히 지원하도록 만들어졌기 때문에 이번 강좌를 통해서 배우게 되는 기본 Python 문법은 다른 Python 버전에서도 그대로 적용이 됩니다. 그럼 기본 문법을 알아보도록 하죠. ^^

꼭 기억하세요!: 이전 장에서도 언급하였듯이 우리가 이 강좌 내내 사용할 기본 프로그램은 IronPython 콘솔이라고 하였지요? IronPython 콘솔 프로그램인 ipy.exe를 실행하셔야 합니다. 콘솔 창이 나타나도록 해주세요. 그리고 특별한 설명이 없어도 >>> 라는 프롬프트는 입력하지 않아야 한다는 것은 알고 계시죠?

>>> 2+2

위의 수식을 입력하고 실행하면 당연히 숫자 4를 반환할 것입니다. 이전 장에서 공부하였던 수식 계산을 다시 참조해 보세요. ^^

>>> print "Blah Blah Blah"
>>> print 'Something Special in FePy!'

print 라고 하는 명령어는 표준 출력 장치 (특별한 언급이 없는 한 콘솔 윈도우나 콘솔 그 자체를 의미하지만 리디렉션 처리를 한다면 프린터나 혹은 다른 응용프로그램에서 사용하는 파일 핸들로도 열릴 수 있기 때문에 화면이라 하지 않고 표준 출력 장치라고 했습니다. 혼동 없으시길 바랍니다.)에 지정한 문자열을 출력하는 명령어입니다.

문자열을 사용하는 방법이 어색하지 않다는 것을 확인할 수 있습니다. C나 C++에서 해왔던 것 처럼 겹 따옴표를 사용하거나 겹 따옴표가 아닌 홑 따옴표를 사용하여 문자열로 지정하고 싶은 내용을 감싸기만 하면 되는 것입니다.

>>> x = 10

위의 구문은 x라고 하는 변수를 할당하고 그곳에 10을 대입한 것입니다. Python에서의 변수 선언은 위와 같이 극도로 단순합니다. 위에서는 정수 10을 지정했지만 정수가 아니라 일반 문자열, 소수는 물론 복소수, 각종 객체 등을 지정하거나 생성할 수 있습니다. Python은 복소수를 내부적으로 지원하므로 좀 더 복잡한 수치 계산을 필요로 하는 수학 시뮬레이션 등에서 요긴하게 사용할 수 있는 언어입니다.

>>> print x

위에서 x라는 것을 선언하였으니 print 구문을 즉시 응용해보도록 하죠. print는 문자열을 받는 것 처럼 보였지만 정확히 말하면 어떤 형식이든 객체는 다 받게 되어있습니다. 만약 숫자가 들어온다면 숫자를 문자열로 바꾸어 출력할 것이고, 문자열이만 그대로, 일반적인 객체라면 객체의 형식과 메모리 주소 같은 정보를 표현할 것입니다.

콘솔 윈도우이기때문에 설명을 하나 더하도록 하지요. 콘솔 모드에서는 프로그램의 디버깅도 해야하기 때문에 print 구문을 이용하지 않았어도 숫자의 값이나 객체의 정보가 출력되곤 합니다만 print 구문을 이용하지 않는 경우 문자열에 포함된 이스케이프 문자들을 이스케이프 처리하여 표시합니다. 즉, 줄 띄우기나 탭 등을 정확히 표현하지 않는 대신 \n이나 \t 같은 기호로 대신 표시한다는 뜻입니다.

기본적인 변수 선언과 화면 출력 방법은 확인하였습니다. 이제 그러면 진짜 언어 답게 쓸 수 있기 위해서 필요한 조건문과 반복문을 배워보도록 하죠.

IronPython 콘솔을 이용하는 동안 우리는 한 줄에 실행될 수 있는 명령문만을 입력해왔습니다. 하지만 지금부터 사용할 조건문이나 반복문은 한 줄에 끝나는 경우는 드뭅니다. 너무 당연한 사실이죠. 그러면 한 줄 이상을 입력할 방법이 없지 않느냐라고 궁금해하실텐데요. 그렇진 않습니다. 여러줄 입력 모드에 돌입하게 되면 제가 위에서 사용했던 >>> 프롬프트 대신 ... 이라는 프롬프트로 바뀌게 됩니다. 이 상태에서 명령어를 입력하고 있는 것이라면 여러줄 모드를 의미합니다. 그리고 여러줄 입력의 끝을 알리는 것은 간단합니다. ... 이라는 프롬프트가 나타난 상태에서 그냥 Enter 키를 입력하면 여러 줄 입력이 끝났으며 실행하겠다는 뜻으로 전달됩니다.

계속 이어서, 우리가 아까전에 설정한 변수 x를 활용하여 조건문을 연습해보도록 합시다. 그리고 들여쓰기 기호를 명시하기 위하여 [탭] 이라는 약물기호를 사용하겠습니다. 그대로 타이핑하지 마시고 반드시 Tab 키나 Space 키를 눌러서 띄워주십시오.

>>> if x == 4:
... [탭]print "x is 4!"
... else:
... [탭]print "x is not 4!"
...

위와 같이 입력한 후 실행하면 두 번째 조건으로 선택될 것입니다. 왜냐면 x의 값은 여전히 10이기 때문이겠지요. 이제부터 중요한 것을 설명하겠습니다.

여러줄에 걸쳐서 입력이 필요한 명령 구문을 사용하는 경우 반드시 그 줄의 끝에는 : 기호를 붙여야만 합니다. 그렇지 않으면 그냥 끝나는 단문으로 인식하기 때문에 실행할 수 없다는 오류를 띄우겠지요. 이렇게 여러 줄 입력 모드가 시작됩니다. 그리고 서두에서 이야기하였듯이 탭 들여쓰기가 중요하다고 하였습니다. 탭 들여쓰기가 이루어진 지점은 : 기호가 붙은 지점에 대하여 하위 세그먼트라는 의미가 됩니다. 만약 이 탭이 사라진다면 의미가 일치하지 않게되므로 잘못된 구문이 되는 것입니다. 위의 예제에서는 탭 들여쓰기를 한 번만 하였지만 앞으로 우리는 필요한 만큼 탭 들여쓰기를 계속하여 중첩 시킬 수도 있습니다.

두 개체를 비교하기 위한 연산자로 위에서는 == 연산자를 사용하였습니다. 같지 않음을 표현하기 위하여 != 연산자나 <> 연산자를 사용합니다.

이제 우리가 자주 사용하는 반복문을 배워보도록 합니다. 반복문도 여러 줄 입력을 사용해야 하므로 위에서 설명한 원리를 그대로 적용해야겠습니다.

>>> for i in range(x):
... [탭]print i
...

내장 함수 하나를 소개합니다. range() 함수인데 반복문을 사용할 때에도 사용하지만 오름차순으로 정렬되어있으면서 등간격으로 숫자를 채워넣은 배열을 만드는 유용한 함수입니다. 위의 결과대로라면 0부터 9까지의 값이 한줄씩 차례로 출력될 것입니다.

range() 함수에 대해서 좀 더 살펴보도록 합니다. range() 함수는 세 가지 버전의 오버로드를 가지고 있는데 아래와 같습니다.

* object range(object stop): 0부터 stop까지를 등간격 1로 채웁니다.
* object range(object start, object stop): start부터 stop까지를 등간격 1로 채웁니다.
* object range(object start, object stop, object step): start부터 stop까지를 등간격 step으로 채웁니다.

지금의 for 구문의 사용법은 C#의 foreach나 Visual Basic .NET의 For Each를 연상하시면 되겠습니다. 여기서의 for 구문은 Index 증감 연산을 기반으로하는 것이 아니라 Iteration을 기반으로 사용한 것입니다. 그래서 in 연산자를 사용하는 것이지요.

긴 설명이었지만 차분히 따라하시면서 익히면 재미있으실 겁니다. 다음 장에서는 함수에 관한 실제를 살펴보도록 하겠습니다.

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

IronPython은 CodePlex.com이라는 오픈 소스 프로젝트 호스팅 사이트를 통하여 다운로드받으실 수 있습니다. 지금은 본 강좌에 첨부된 IronPython 프로그램 파일이 담긴 이 ZIP 파일을 편리한 디렉터리에 압축을 풀어주시기만 하면됩니다.

압축된 파일을 풀면 ipy.exe 파일과 ipyw.exe 파일, IronMath.dll 파일, IronPython.dll 파일을 비롯하여 문서, 예제 파일들이 저장될 것입니다. 이 중에서 핵심이 되는 것은 직접 언급한 네 가지 파일입니다. 각각의 파일의 용도를 살펴보겠습니다.

ipy.exe: IronPython 대화형 콘솔 프로그램입니다. 이 강좌의 대부분은 이 프로그램을 이용하여 실행하는 것을 기준으로 합니다.

ipyw.exe: IronPython을 WinMain 스타일로 구현한 프로그램입니다. 콘솔 윈도우가 나타나는 것이 아니며 또한 윈도우용 GUI가 나타나는것도 아닙니다. 다만, 외부에서 실행할 때 이 프로그램에 대한 파라미터로 Python Script 파일을 넘겨주었을 때 대리로 수행해주는 역할을 하게 됩니다.

IronMath.dll: IronPython의 수학적 능력이 발휘될 수 있는 원동력이 바로 이 파일인데, BigInteger 클래스와 Complex64 구조체를 제공합니다. BigInteger는 통상적으로 가장 크다고 알려진 Visual C++의 __int64보다 더 큰 수를 다룰 수 있고, Complex64의 경우 복소수를 다룰 수 있으므로 허수의 개념을 지원합니다. IronPython을 어떤 형식으로 사용하든 꼭 필요한 파일입니다.

IronPython.dll: IronPython의 핵심 기능은 이곳에 모두 밀집되어있습니다. 자세히 언급하지 않더라도 생략하면 안되는 파일입니다. 이름만 봐도 알 수 있는 사실이지요.

그 외에 있는 폴더나 파일들은 한 번씩 살펴보시면 IronPython에 관한 또 다른 정보를 얻으실 수 있을 것입니다. 이 강좌를 통해서도 각종 예제들은 수시로 언급하고자 합니다.

기본적인 파일들에 대한 설명이 끝났으니 이제 본론으로 들어가서 ipy.exe로 간단히 재미있는 일들을 수행해보도록 하지요. ipy.exe를 실행한 후 잠시 기다리시면 다음과 같은 형태의 화면이 콘솔에 나타날 것입니다.

IronPython 1.0.60816 on .NET 2.0.50727.42
Copyright (c) Microsoft Corporation. All rights reserved.

>>>

IronPython의 버전과 함께 현재 IronPython이 사용하는 .NET Framework의 버전도 같이 표시됩니다. 현재는 .NET Framework 3.0을 설치한 후에라도 내부적으로는 .NET Framework 2.0을 사용하고 있기 때문에 여전히 2.0의 버전대를 표시하고 있습니다. 그리고 Microsoft의 프로젝트임을 명시하는 글귀도 보입니다. 마지막으로 세번째 줄의 프롬프트부터 우리가 원하는 것을 입력하면 됩니다.

IronPython은 단순한 스크립트 언어일 뿐만이 아니라 훌륭한 공학용 계산기의 역할을 해냅니다. 우리가 해보고 싶은 "재미있는 것"이란 바로 공학용 계산기의 기본기를 살펴보는 일입니다. 다같이 따라해 봅시다.

설명) 프롬프트상에서 입력한 내용임을 구분짓기 위하여 >>> 기호를 앞에 붙입니다. 실제로는 >>> 기호를 빼고 입력해야 정상적으로 실행이 되겠지요? ^^

>>> 1+2
3
>>> (56+44)
100
>>> (56+44) * 3 / 8
37
>>> 1 / 0
Traceback (most recent call last):
File , line 0, in <stdin>##22
ZeroDivisionError: 0으로 나누려 했습니다.
>>>

어떤가요? 괄호를 이용하여 묶은 수식도 척척 계산해 냅니다. 하지만 우리가 사용하고 싶은 진짜 공학용 계산기의 모습은 훨씬 다양한 것입니다. 뭔가 빠졌지요? 맛보기로 math 모듈을 참조하여 어떤 기능을 사용할 수 있는 살펴보겠습니다.

>>> import math
>>> dir(math)
['__builtins__', '__class__', '__dict__', '__doc__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh']
>>> math.sin(30)
-0.988031624093
>>>

math라는 모듈 안에 우리가 사용하고 싶어하는 수학적 함수들이 모두 프로그래밍 되어있습니다. IronPython에서의 모듈이란 C#의 Static Class (또는 Static 멤버를 1개 이상 포함하는 보통의 Class도 포함됩니다.), Visual Basic .NET의 Module과 같은 개념이며 IronPython도 실제로 그렇게 처리해줍니다. 그리고 dir() 이라는 내장 함수는 IronPython이 객체를 어떻게 다룰 수 있는가에 대한 의문을 일거에 날려버리는 유명한 함수입니다. DOS나 UNIX에서 특정 디렉터리 내에 속한 개체들을 살피기 위하여 사용하던 그 dir 명령과 다르지 않아서 금방 머리에 들어옵니다.

좀 더 복잡한 계산식을 계산하시고 싶으시다면 지금 당장 사용해 보세요. 한 가지 더 알려드리면 이후 IronPython을 종전의 .NET 응용프로그램에서 사용할 경우 지금의 명령문이나 스크립트들을 모두 사용할 수 있다는 것입니다. 즉, 계산식을 분석하기 위하여 고민할 필요 없이 간단히 IronPython을 사용하기만 해도 되는 것입니다.

다음 Chapter에 들어와서는 Python의 실제 문법을 살펴보도록 하겠습니다. 많은 기대 바랍니다. ^^

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)

IronPython은 개발 초기 단계부터 많은 사람들의 관심을 이끌었던 프로젝트입니다. C, C++, Java에서 사용이 가능했던 Python을 .NET Framework위에서 사용할 수 있게 되니까요. 뿐만 아니라 개발 과정 내내 발표된 성능 측정 자료는 점점 더 많은 사람들이 IronPython에 흥미를 느낄 수 있도록 해주었습니다. 부분적이기는 하지만 우리가 빠르다고 여겨왔던 C, C++ 기반의 Python보다 더욱 속도가 빠르기까지 하였습니다. (함수 호출, 수식 계산과 같은 부분은 종전의 Python이 1초라고 한다면 오차를 무시하고 약 0.3초 가량이 더 빠릅니다. Java 기반의 Python에 비해서는 무려 50배 이상 더 빠릅니다.)

IronPython은 현재 공식적으로 버전 1.0이 발표된 상태입니다. IronPython의 등장은 단순히 소프트웨어 하나가 더 늘어난 것이 아니라 .NET Framework를 더욱 풍성하게 가꾸어줄 양분이 늘어난 것으로 해석해야 할 것입니다. 왜냐하면 컴파일 언어 기반이었던 .NET Framework에는 스크립트 언어만이 가질 수 있는 확장성과 다양성이 다소 결여되어있었기 때문입니다.

우리가 앞으로 개발할 프로그램에 IronPython을 사용하게 된다면 이전보다 더욱 역동적인 프로그램을 제작할 수 있습니다. 우리가 잘 알고 있는 스크립트 언어 활용의 대표적인 사례인 Microsoft Office와 마찬가지로 현재 프로그램에서 생성한 객체들이나 노출된 API들을 프로그램의 자동화에 사용할 수 있을 뿐만 아니라 Microsoft Office가 지원하는 Script Programming 기능처럼 우리의 프로그램에도 그런 기능을 넣을 수 있게 됩니다. 그리고 IronPython만의 특전이 하나 더 있다면 그것은 바로 문자열로 된 수식 계산이 단 한 번의 호출로 처리될 수 있다는 점입니다. Python 패키지들이 흔히 제공해왔던 대화형 Python Shell에서 해왔던 것과 마찬가지입니다. 오히려 더 좋습니다. 단순한 수식일 수도 있지만 수식 안에 .NET Framework의 API 함수 호출 구문이나 자신이 만든 수식 계산 루틴을 담는 함수 호출 구문을 추가할 수도 있으니까요.

IronPython의 기본적인 문법을 익힘과 동시에 IronPython을 어떻게 기존 응용프로그램에 통합할 수 있는지를 이 강좌를 통하여 차근차근히 살펴보도록 하겠습니다. 이 강좌가 많은 도움이 되기를 바랍니다.

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by Windows Azure MVP 남정현 (rkttu.com)