원 재료들

우리는 무엇을 다룰 것인가?
  • 데이타란 무엇인가
  • 변수란 무엇인가
  • 데이타 형과 그것으로 무엇을 할 수 있는가
  • 우리 자신만의 데이타형을 정의하기
  • 소 개

    어떠한 종류의 창조적인 활동에서도 우리는 세 가지의 기본적인 요소를 필요로 한다: 도구와, 재료 그리고 기술. 예를 들어 내가 그림을 그릴 때는 도구들은 붓, 연필 그리고 팔레트이다. 기술은 덧칠하고, 혼합하고, 흩뿌리고 등등 과 같은 것이다. 마지막으로 재료는 페인트, 종이 그리고 물이다. 비슷하게 내가 프로그래밍을 할 때는, 나의 도구는 프로그래밍 언어, 운영체제와 하드웨어이다. 기술은 이 전 섹션들에서 우리가 논의한 프로그래밍 구조들이다 그리고 재료는 내가 처리해야할 데이타이다. 이 장에서 우리는 프로그래밍의 재료들을 살펴볼 것이다.

    이 장은 대단히 긴 섹션이며 그 본성상 여러분은 약간은 무미건조하게 느낄 것인데, 그래도 좋은 소식은 여러분이 한번이라도 그 모두를 읽을 필요는 없다는 것이다. 이 장은 먼저 사용가능한 가장 기본적인 데이타 형을 살펴보고 계속하여 어떻게 우리는 항목들의 모임을 다룰 것인지에 대하여 나아가고 마지막으로 약간 더 진보된 재료들을 살펴볼 것이다. 집합형 재료들을 다룬, 이 장을 생략할 수가 있다. 다음 몇 개의 장을 다루어 보고 그리고 나서 이 장으로 돌아 오라. 그 때 우리는 더욱 진보된 조각들을 사용하기 시작할 것이다.

    데이타

    데이타는 모든 사람들이 사용을 하지만 실제로 이해하는 사람은 드문 용어들 중의 하나이다. 내 사전은 그것을 다음과 같이 정의하고 있다:

    "결과를 이끌어 낼수 있는 사실들 혹은 숫자들; 정보"

    그것으로 큰 도움은 안되겠지만 적어도 출발점은 제공해 준다. 프로그래밍 용어로 데이타가 어떻게 사용되는 지를 살펴봄으로써 우리가 사실을 명쾌하게 정리할 수 있는지 살펴보자. 데이타는 가공되지 않은 정보이다, 그것을 여러분의 프로그램이 처리한다. 데이타가 없이는 프로그램은 어떠한 유용한 기능도 수행할 수 없다. 프로그램은 때로는 데이타의 형type에 따라서, 여러가지 방식으로 데이타를 처리한다. 각 데이타의 형은 또한 많은 수의 처리방법operations들을 가진다 - 그것으로 여러분 데이타에 처리를 한다. 예를 들어 우리는 숫자들을 더할 수 있다는 것을 보았다. 덧셈은 수치형의 데이타에 사용되는 처리방법이다. 데이타는 여러가지 형태가 있다. 우리는 가장 일반적인 형태들과 그 형태에 사용가능한 처리방법을 살펴볼 것이다:

    변 수

    데이타는 여러분의 컴퓨터메모리에 저장된다. 여러분은 이것을 편지를 분류하기 위하여 우편방에서 사용되는 상자들로 가득한 큰 벽이라고 비유할 수 있다. 여러분은 편지를 어떤 상자에서 넣을 수 있지만, 상자에 적당한 목적지 주소가 붙어있지 않다면 그것은 아무런 의미없는 일이다. 변수들은 여러분의 컴퓨터 메모리에 있는 상자들에 붙여진 라벨과 같은 것이다.

    데이타의 모습이 어떠한지를 이해하는 것은 이해할 수록 좋은 것이지만 그것을 다루기 위해서는 거기에 접근할 필요가 있으며 그것이 바로 변수가 사용되는 이유이다. 프로그래밍 용어로 우리는 데이타 형의 실체instances를 만들수 있고 그것들을 변수에 할당할 수 있다. 변수는 컴퓨터 메모리의 어디엔가 있는 특정한 지역에 대한 참조reference이다. 이러한 지역은 데이타를 가지고 있다. 어떤 컴퓨터 언어에서는 변수는 자신이 지시하는 그 데이타의 형과 반드시 일치해야만 한다. 그러한 변수에 잘못된 형태의 데이타를 할당하려는 어떠한 시도도 에러를 야기할 것이다. 어떤 프로그래머들은 이러한 형태의 시스템을 선호한다, 이러한 시스템은 탐지하기 어려운 미묘한 버그들을 방지할 수 있기 때문에 정적형태static typing라고 알려져 있다.

    파이썬에서 변수는 자신에게 할당된 데이타의 형을 취한다. 파이썬은 그 형태를 유지할 것이고 여러분이 (문자열을 숫자등에 더하려고 하는 것과 같은) 괴이한 방식으로 데이타를 섞어 쓰려고 하면 여러분에게 경고를 할 것이다. (예제의 에러 메시지가 기억나는가? 그것은 단지 그런 종류의 예일뿐이다.) 우리는 한 변수가 지시하는 데이타의 형을 그 변수를 재할당함으로써 바꿀수 있다.

    >>> q = 7         # q is now a number
    >>> print q
    7
    >>> q = "Seven"   # reassign q to a string
    >>> print q
    Seven
    

    'q'는 숫자 7을 지시하도록 처음에 설정되었음을 주목하라. 우리가 문자열 "seven"을 그곳에 할당할 때까지 'q'는 그 값을 유지한다. 그런식으로, 파이썬의 변수는 어떤값을 지시하든지 그 형을 유지하지만, 우리는 그 변수를 단순히 재할당함으로써 그것들이 지시하는 것을 변경할 수 있다. 그 순간에 원래의 데이타는 '사라지고' 파이썬은 (다른 변수가 또 그것을 지시하지 않는 한)그것을 메모리로부터 지울 것이다. 이것은 쓰레기 수집 garbage collection.이라고 알려져 있다.

    쓰레기 수집은 가끔 잠시 한번 들려서 라벨없는 상자에 들어 있는 편지들을 없애는 편지방 직원에 비유될 수 있다. 그가 만약 소유자 혹은 주소를 그 편지에서 발견할 수 없다면 그는 그것들을 쓰레기통에 버린다. 데이타형의 몇 가지 예제들을 살펴보고 이러한 모든 것들이 어떻게 맞아 떨어지는지 알아보자

    기본적인 데이타 형

    기본적인 데이타 형은 이른바 그들이 우리가 다룰 수 있는 가장 기본적인 데이타 형이기 때문에 그렇게 불려진다. 더욱 복잡한 데이타 형은 실제로는 기본적인 형의 결합이다. 이것들은, 빌딩 블록과 같아서 다른 모든 형들이 이 위에 세워지며, 컴퓨팅의 토대가 된다. 이것에는 문자, 숫자 그리고 불리언 형이라고 불리우는 것 등이 포함된다.

    문자열

    우리는 이미 이것들을 보았다. 그것들은 말 그대로 죽 늘어선 혹은 연속적인 문자들이어서 여러분의 스크린에 출력될 수 있다. (사실 거기에는 출력될 수 없는 제어 문자 control characters들도 역시 있을 수 있다.)

    파이썬에서, 문자열은 여러가지 방식으로 표현될 수 있다:

    단일 인용부호를 가지고:

    'Here is a string'

    이중 인용부호를 가지고:

    "Here is a very similar string"

    세개짜리 이중인용부호를 가지고:

    """ Here is a very long string that can
        if we wish span several lines and Python will
        preserve the lines as we type them..."""
    

    마지막의 특별한 사용법은 파이썬 우리가 스스로 만든 함수들을 문서화하는 것이다. - 이것은 나중에 다룰 것이다.

    여러분은 문자열속에 있는 개별적인 문자들을 문자열의 배열로 취급함으로써 접근할 수 있다.(아래의 배열을 참조하라) 또한 그 프로그래밍언어가 보통 제공하는 약간의 처리방법들도 있어서 여러분이 문자열을 다룰수 있도록 도와 준다. - 하부 문자열 찾기, 두개의 문자열을 연결하기, 하나의 문자열을 다른 문자열에 복사하기 등등.

    문자열 연산자

    문자열에 수행가능한 수 많은 처리방식들이 있다. 이러한 것들 중 약간은 파이썬에 내장되었으나 다른 많은 것들은 모듈로 제공되어 여러분은 반드시 (간단한 연속열 섹션에서 sys모듈을 다룬 것과 같이)그 모둘을 수입할 필요가 있다.

    문자열 연산자

    연산자 설 명
    S1 + S2 S1과 S2를 연결하기
    S1 * N S1을 N번 반복하기

    우리는 이것들이 다음 예제에서와 같이 작동하는 것을 볼수 있다:

    >>> print 'Again and ' + 'again'    # string concatenation
    Again and again
    >>> print 'Repeat ' * 3		        # string repetition
    Repeat Repeat Repeat
    >>> print 'Again ' + ('and again ' * 3)  # combine '+' and '*'
    Again and again and again and again
    

    우리는 또한 문자열을 변수에 할당할 수도 있다:

    >>> s1 = 'Again '
    >>> s2 = 'and again '
    >>> print s1 + (s2 * 3)
    Again and again and again and again
    

    가장 마지막의 두 개의 예제는 똑 같은 출력을 산출하고 있음을 주목하라.

    BASIC의 문자열 변수

    베이직에서, 만약 변수가 문자열 배열이라면 여러분은 반드시 그 이름을 $로 끝내야 한다. 그렇게 하고 나면 다시는 그 변수에 숫자를 할당할 수 없다. 마찬가지로, (%로 끝나는) 정수형 변수라면 여러분은 문자열을 그것에 할당할 수 없다. 베이직은 어떤 것으로도 끝나지 않는 '익명 변수'를 허용하기는 한다. 그렇지만 이것들은 실수이거나 혹은 정수이거나 오로지 숫자만을 저장할 수 있다. 여기에 베이직에서 사용하는 문자열 변수의 예제가 있다:

    DIM MyString$
    MyString$ = "Hello there!"
    PRINT MyString$
    

    Tcl 문자열

    Tcl은 내부적으로 모든 것에 문자열을 사용한다. 사용자의 관점에서 본다면 그렇지만 이것은 보통은 확실하게 보이지 않는다. 명시적으로 문자열을 다룰 때는 여러분은 그것을 이중인용부호로 둘러싸야 한다. Tcl에서 하나의 값을 변수에 할당하기 위해서는 set명령어를 사용하라 그리고 문자열 변수를 읽기 위해서는 (혹은 실제로 Tcl에서는 어떤 변수도 마찬가지이다.) '$'기호를 그 이름앞에 놓아라, 다음과 같이:

    % set Mystring "Hello world"
    % put $Mystring
    

    주의: Tcl 과 BASIC에서는 오로지 이중인용부호만이 문자열에 사용될 수 있다.

    정 수

    정수는 대단히 큰 음의 값으로부터 대단히 큰 양의 값까지 소수점을 포함하지 않은 수이다. 그것은 꼭 기억해야할 중요한 점이다. 보통 우리는 숫자들이 크기에 있어 제한 되지 않는다고 생각하지만 컴퓨터에서는 상한과 하한이 존재한다. 상한값의 크기는 MAXINT라고 알려져 있으며, 숫자를 표현하기 위하여 여러분의 컴퓨터가 사용하는 비트의 숫자에 의하여 결정된다. 오늘날의 대부분의 컴퓨터에서는 32비트가 기본이며 그래서 MAXINT값은 약 20억 정도가 된다.

    양과 음의 값을 가지는 숫자는 부호있는 정수signed integers라고 알려져 있다. 여러분은 물론 0 을 포함하여, 양의 숫자로만 제한된 부호없는 정수unsigned integers를 가질 수도 있다. 이것은 더 큰 최대값을 MAXINT의 두배 혹은 40억 가량으로 사용가능하다는 것을 의미하는데 우리가 음의 수를 나타내기 위하여 그 전에 사용했던 공간들을 사용하여 양의 숫자들을 더욱 많이 나타낼 수 있기 때문이다.

    정수는 크기가 MAXINT값으로 제한 되어 있으므로 두 개의 정수를 더하여 함계가 MAXINT값보다 크게 된다면 합계는 에러를 발생시킨다. 어떤 시스템/언어에서는 잘못된 값은 단순히 그대로 반환될 뿐이다( 보통 어떤 비밀스런 표식이 제기되면 여러분이 생각하기에 그것이 올바르게 설정 되었는지를 여러분은 점검할수 있다.) 보통 에러 조건이 야기되면 여러분의 프로그램은 그 에러를 처리할 수 있거나 아니면 프로그램은 종표한다. 파이썬은 후자의 접근방식을 취하고 있고 반면에 Tcl은 전자를 채택하고 있다. 베이직도 에러를 야기하지만 에러를 잡을 수 있는 방법은 제공하지 않는다.( 적어도 난 어떻게 하는지 모른다!)

    수학적 연산자

    우리는 이미 대부분의 수학적 연산자를 보았다. 여러분은 '단순한 연속열'의 장에서 그것들이 필요했었다. 그렇지만 요약하자면:

    수학적 그리고 비트 연산자

    연산자 예해 설
    M + NM 과 N 의 덧셈
    M - NM 에서 N 빼기
    M * NM 과 N 의 곱셈
    M / N나누기, M과 N의 형에 따라서 정수 혹은 부동소수점을 결과로 가진다.
    만약 M 또는 N 이 실수라면(아래를 보라) 그 결과는 실수가 될 것이다.
    M % N나머지: M을 N으로 나눈 나머지를 찾는다.
    M**N지수화: M 을 N제곱

    우리는 가장 마지막 예제를 전에 본적이 있다. 그래서 어떤 정수형 변수를 만들고 지수 연산자를 사용하는 예제를 하나 살펴보자:

    >>> i1 = 2     # create an integer and assign it to i1
    >>> i2 = 4
    >>> i3 = 2**4  # assign the result of 2 to the power 4 to i3
    >>> print i3
    16
    

    BASIC 정수

    BASIC 은 정수에 관해 또 다른 규칙들을 가지고 있다. 정수형 변수를 선언하기 위하여 베이직에서 여러분은 아무것도 붙이지 않은 이름 그대로를 사용하던가 우리가 원하는 것이 정수라는 신호를 베이직에게 줄 수가 있다 (이것이 좀더 효율적일 것이다.) 우리는 이름을 '%'로 끝냄으로서 이것을 할 수 있다:

    FOO = 8   REM FOO can hold any kind of number
    BAR% = 9  REM BAR can only hold integers
    

    BASIC에서 정수형 변수에 관하여 마지막 주의사항:

    i% = 7
    PRINT 2 * i%
    i% = 4.5
    PRINT 2 * i%
    

    4.5가 i%에 할당된 것이 작동하는 것같이 보이지만 단지 정수부분만이 실제로 할당되었다는 것을 주목하라. 이것을 보면 파이썬이 정수나눗셈을 다루던 방식이 생각난다. 모든 프로그래밍 언어는 자신만의 이러한 개성을 가진다!

    Tcl 숫자

    지난번에 언급한 것같이 Tcl은 모든 것을 내부적으로 문자열로 저장한다, 그렇지만 사용자는 이것 때문에 다른 특별한 차이를 느끼지는 않는데 왜냐하면 Tcl이 덮개 아래에서 그 값을 숫자로 바꾸어주고 또 다시, 원래의 값으로 환원시켜주기 때문이다. 그렇게 모든 숫자의 크기에 대한 모든 제한 사항들은 여전히 적용된다.

    Tcl에서 숫자를 사용하는 것은 대부분의 언어보다는 약간은 더 복잡한데 왜냐하면 어떤 계산을 하고자 한다면 여러분은 그 인터프리터에게 계산이 필요하다는 신호를 주어야만 하기 때문이다. 여러분은 그것을 expr명령어를 사용하여 계산을 한다:

    % put [expr 6 + 5]
    11
    

    Tcl은 각괄호를 보고서 마치 명령어 라인에서 타이프 된 것 같이, 그 부분을 먼저 평가한다. 평가중에 expr 명령어를 보게 되면 계산을 수행한다. 결과는 put 명령어로 스크린에 출력된다. 만약 여러분이 직접적으로 그 합계를 출력하려고 한다면 Tcl은 단지 "6 + 5"만을 출력할 것이다:

    % put 6 + 5
    6 + 5
    

    실 수

    이것은 분수이다. 그것은 대단히 큰 수를 나타낼 수 있어서, MAXINT보다 훨씬 더 크지만, 정밀도는 떨어진다. 다시 말하면 정확히 동일해야만 하는 두 개의 실수가 컴퓨터에 의하여 비교될 때는 그렇지 않다는 것이다. 이것은 컴퓨터가 근사치로 어림셈을 하기 때문이다. 그런식으로 4.0은 컴퓨터에 의해서는 3.9999999.... 또는 4.000000....01 로 나타내어질 수 있다. 이러한 어림셈은 대부분의 목적에는 충분하지만 때로는 이것은 대단히 중요한 문제이다! 만약 여러분이 실수를 사용했을때 우스운 결과를 얻었다면, 이것을 명심하라.

    부동소수점 수는 수치를 정수값으로 잘라내는 능력과 함께 정수와 똑 같은 처리방식을 가진다.

    복소수 혹은 허수

    여러분이 과학적 혹은 수학적 배경을 가지고 있다면 여러분은 복소수에 대하여 궁금할 것이다. 그렇지 않다면 여러분은 복소수를 들어보지도 않았을 수 있다! 어찌되었든 어떤 프로그래밍 언어에서는, 파이썬을 포함하여, 복소수 형을 내부적으로 지원하며 반면에 다른 언어들은 복소수를 다룰 수 있는 함수의 라이브러리를 제공해준다. 그리고 여러분이 묻기 전에 (내가 먼저 말하면), 행렬 역시 똑 같은 것이 적용된다.

    파이썬에서 복소수는 다음과 같이 표현된다:

    (real+imaginaryj)
    

    그런식으로 단순한 복소수의 덧셈은 다음과 같다:

    >>> M = (2+4j)
    >>> N = (7+6j)
    >>> print M + N
    (9+10j)
    

    모든 정수 연산은 또한 복소수에도 적용된다.

    불리언 값 - True and False

    제목이 말해주는 바와 같이, 이러한 형태는 오직 2가지 값만을 가진다 - 참 true 이거나 혹은 거짓 false만을 가진다. 어떤 언어는 불리언 값을 직접 지원하고, 다른 언어에서는 어떤 수치 값 (보통은 0)은 거짓을 나타내고 다른 값들( 1혹은 -1)등은 참을 나타낸다는 관례를 사용한다.

    불리언 값은 때로는 "진리 값"이라고 알려져 있는데 왜냐하면 무엇인가가 참인가 혹은 아닌가하는 것을 검증하는데 그들이 사용되어지기 때문이다. 예를 들어 여러분이 모든 파일을 한 디렉토리에 백업하는 프로그램을 작성한다면 여러분은 각 파일을 백업하고 운영체제에게 다음 파일의 이름을 요구할 수도 있다. 만약 저장해야할 더 이상의 파일이 없다면 운영체제는 빈 문자열을 반환할 것이다. 여러분은 그러면 그 이름이 빈 문자열인지를 점검해 볼수 있으며 그 결과를 불리언 값( 빈문자열이면 참)으로 저장할 수 있다. 여러분은 어떻게 우리가 그 결과를 사용하는지 이 강좌의 후반부에서 보게 될 것이다.

    불리언 (혹은 논리적) 연산자

    연산자 예제설 명결 과
    A and B그리고A,B 둘다 참이면 참, 그렇지 않으면 거짓.
    A or B또는A,B 둘 중 하나만 참이면 참. A 와 B 모두 거짓이면 거짓.
    A == B동등A 가 B 와 같으면 참.
    A != B
    또는
    A <> B
    같지 않음A 가 B 와 같지 않으면 참.
    not B부정B 차 참이 아니면 참

    주 의: 가장 마지막의 예제는 한개의 값을 다루며, 다른 것들 모두는 두 개의 값을 비교한다.

    집합형

    컴퓨터 과학은 집합과 그 것의 다양한 행태들을 연구하는데에 몰두해 왔다. 때로는 집합은 그릇이라고도 불리운다. 이 섹션에서 우리는 먼저 파이썬에서 지원되는 집합형들을 살펴보고 여러분이 다른 언어에서 마주치게 될 다른 종류의 집합형에 대한 짧은 요약으로 결론을 내려한다.

    Python 집합형들

    리스트

    리스트는 항목의 연속이다. 배열과 다른 점은 그것이 커질수 있다는 것이다 - 여러분이 또 다른 항목을 추가하기만 하면 된다. 그러나 일반적으로 지표화 되어 있지 않아서 여러분은 필요로 하는 항목을 그 리스트를 처음부터 마지막까지 방문해서 각각의 항목이 여러분이 원하던 항목인지 점검을 함으로써 찾아야만 한다. 파이썬이나 Tcl모두 리스트를 내장하고 있다. 베이직에서는 더 어려워서 우리는 리스트를 흉내내기 위해 약간 꼼수적인 프로그래밍을 해야만 한다. 그 대신에 베이직 프로그래머들은 보통 대단히 커다란 배열을 만들어 사용한다. 파이썬 또한 여러분이 리스트를 지표화 할 수 있도록 해준다. 우리가 앞으로 보게 되겠지만 이것은 대단히 유용한 언어 사양이다.

    리스트 처리방법

    파이썬은 집합형에 관하여 많은 처리방법들을 제공해준다. 거의 그들 모두 다 리스트에 적용되며 하부세트도 단지 문자들의 특별한 형태의 리스트일 뿐인 문자열을 포함하여, 다른 집합형에 적용된다. 파이썬에서 리스트를 생성하고 접근하기 위해서 우리는 각괄호를 사용한다. 여러분은 각괄호 한쌍을 아무것도 안에 넣지 않고 사용함으로써 빈 리스트를 만들 수 있으며, 또는 각괄호 안에 있는 값들을 컴마로 분리함으로써 내용있는 리스트를 만들 수도 있다:

    >>> aList = []
    >>> another = [1,2,3]
    >>> print another
    [1, 2, 3]
    

    우리는 지표 숫자를 사용하여 개별적인 요소에 접근할 수 있다. 첫번째 요소의 위치는 0이고, 각괄호 안에다가 사용한다:

    >>> print another[2]
    3
    

    우리는 또한 리스트의 요소들의 값을 비스한 방식으로 변경할 수 있다:

    >>> another[2] = 7
    >>> print another
    [1, 2, 7]
    

    여러분은 음수를 지표숫자로 사용하여 리스트의 마지막으로 부터의 구성원에 접근할 수 있다. -1을 사용하여 가장 마지막 항목을 얻는것은 대단히 흔한 일이다:

    >>> print another[-1]
    7
    

    우리는 또한 새로운 요소를 리스트에 끝에다가 append()연산자(메쏘드)를 사용하여 추가할 수 있다:

    >>> aList.append(42)
    >>> print aList
    [42]
    

    심지어는 리스트안에 또 다른 리스트를 가질 수도 있다, 그런식으로 우리가 두번째 리스트를 첫 번째 리스트에 추가하고자 한다면:

    >>> aList.append(another)
    >>> print aList
    [42, [1, 2, 7]]
    

    결과가 두개의 요소를 가진 리스트이지만 두 번째 요소는 (각괄호[ ]로 둘러싸여 보이는 것같이)그 자체로 리스트라는 것을 주목하라. 이것은 유용하다 왜냐하면 그것으로 우리는 리스트의 리스트를 사용하는 격자나 혹은 표를 구현할 수 있기 때문이다. 우리는 그러면 두개의 지표를 사용하여 요소 7 에 접근할 수 있다.:

    >>> print aList[1][2]
    7
    

    첫번째 지표, 1은 두번째 요소를 추출하고 그 요소는 이번에는 리스트이다. 두번째 지표, 2는 하부리스트의 세번째의 요소를 추출한다.

    요소를 추가하는 것의 반대는, 물론, 그것들을 제거하는 것이며 그러기 위해서 우리는 del명령어를 사용한다:

    >>> del aList[1]
    >>> print aList
    [42]
    

    만약 우리가 두 개의 리스트를 하나로 결합하기를 원한다면 우리는 문자열에서 보았던 똑 같은 '+' 연결 연산자를 사용할 수 있다:

    >>> newList = aList + another
    >>> print newList
    [42, [1, 2, 7], 1, 2, 7]
    

    같은 방식으로 우리는 반복연산자를 적용하여 리스트를 같은 값으로 채울 수 있다:

    >>> zeroList = [0] * 5
    >>> print zeroList
    [0, 0, 0, 0, 0]
    

    마지막으로, 우리는 len() 내장함수를 사용하여 리스트의 길이를 결정할 수 있다:

    >>> print len(aList)
    2
    >>> print len(zeroList)
    5
    

    Tcl 리스트

    Tcl 또한 리스트형을 내장하고 있으며 이러한 리스트를 다루는 다양한 명령어를 가지고 있다. 이러한 명령어들은 'l' 접두사에 의해 식별된다, 예를 들어 linsert,lappend, lindex,등등. 간단한 Tcl리스트를 생성하고 구성원에 접근하는예제는 다음과 같다:

    % set L [list 1 2 3]
    % put [lindex $L 2]
    3
    

    터플 Tuple

    모든 언어가 터플 구조를 제공하는 것은 아니지만 그것을 제공하는 언어에서 터플 구조는 대단히 유용하다. 터플은 실제로는 하나의 단위로 취급될 수 있는 값들의 임의적인 집합일 뿐이다. 여러면으로 터플은 리스트와 닮았다. 그러나 현격한 차이점은 터플은 교환불가능immutable이라는 것이다. 다시말하면 여러분이 터플을 변경할 수 없으며 한번 생성되고 나면 요소를 추가하거나 할수 없다는 뜻이다. 파이썬에서, 터플은 괄호로 간단하게 표시된다. 괄호안에는 컴마로 값들의 리스트를 분리하는 데, 다음과 같다:

    >>> aTuple = (1,3,5)
    >>> print aTuple[1]    # use indexing like a list
    3
    >> aTuple[2] = 7       # error, can뭪 change a tuple뭩 elements
    Traceback (innermost last):
      File "", line 1, in ?
      	aTuple[2] = 7
    TypeError: object doesn't support item assignment
    

    기억해야할 가장 중요한 것은 터플을 정의하기 위하여 괄호가 사용되는 반면에, 지표화하는데에는 각괄호가 사용되며 여러분은 터플을 한번 만들어지고 나면 변경할 수 없다는 것이다. 그것만 빼고는 대부분의 리스트 처리방법들이 또한 터플에도 적용된다.

    사전 혹은 해쉬함수( Hash )

    사전은 이름에서 느껴지는 바와 같이 키와 연관된 값을 포함한다, 같은 방식으로 문자적인 사전도 의미와 단어를 연관시킨다. 그 값은 사전을 키로 지표화 함으로써 검색될 수 있다. 문자적인 사전과 다른 점은 키가 (자주 그렇게 사용됨에도 불구하고) 반드시 문자열이어야 할 필요가 없으나 터플과 숫자를 포함하여 어떠한 형태의 변경불가 형도 가능하다. 비슷하게 키와 연관된 값들은 어떠한 종류의 파이썬 데이타형도 가능하다. 서전은 보통 내부적으로 해쉬테이블이라고 알려져 있는 진보된 프로그래밍 기술을 사용하여 구현된다. 그러한 이유로 사전은 때로는 해쉬라고도 불리운다. (해쉬라는) 마약과는 전혀 상관 없다!

    사전의 값에 접근하려면 키를 통해야 하기 때문에 여러분은 유일한 키로 요소를 집어 넣을 수만 있다. 사전은 대단히 유용한 구조이며 파이썬에서는 내장형으로 제공된다. 그렇지만 여러 다른 언어에서는 여러분은 모듈을 사용하던가 혹은 심지어 직접 만들어 써야만 한다. 우리는 사전을 여러가지 방법으로 사용할 수 있으며 우리는 후에 풍부한 예제들을 보게 될 것이다. 그러나 지금 여기에, 파이썬에서 어떻게 사전을 만드는지를 보이면, 요소들로 사전을 채우고 그것들을 다시 읽어보라:

    >>> dict = {}
    >>> dict['boolean'] = "A value which is either true or false"
    >>> dict['integer'] = "A whole number"
    >>> print dict['boolean']
    A value which is either true or false
    

    우리가 사전을 활괄호로 초기화하고, 그리고는 각괄호를 사용하여 값들을 할당하고 읽었음을 주목하라.

    사전의 내부적인 구조 문제로 인하여 사전은 우리가 지금까지 보아온 많은 집합형 연산자들을 지원하지 않는다. 연결, 반복 또는 추가 연산등은 작동하지 않는다. 우리가 사전의 키에 접근하도록 도와주는 keys()함수를 우리는 사용할 수 있는데 그 함수는 사전에 있는 키들의 리스트를 반환해준다.

    여러분이 약간 지겹다면, 여기에서 여러분은 다음 장 으로 점프할 수 있다. 우리가 지금까지 언급하지 않은 데이타형과 마주치기 시작할 때 반드시 돌아와 이 장을 끝내야만 한다는 것을 기억하라.

    다른 집합 형

    배열 혹은 벡터

    지표화 되어 쉽고 빠르게 검색가능한 항목들의 리스트.
    보통 여러분은 얼마나 많은 항목을 저장하기를 원하는지 먼저 말해 주어야만 한다. 내가 A라고 부르는 배열을 가지고 있다고 하자, 그러면 나는 세번째 항목을 A에 A[3]이라고 씀으로써 추출할 수 있다. 배열은 베이직에서 기본적이다, 사실 집합형으로는 유일하게only 내장되었다. 파이썬에서 배열은 리스트를 사용하여 흉내내어지며 Tcl에서는 사전을 사용하여 구현된다.

    베이직에서 배열의 사용예는 아래와 같다:

    DIM Myarray(20) REM Create a 20 element array
    MyArray(1) = 27
    MyArray(2) = 50
    FOR i =1 TO 5
       PRINT MyArray(i)
    NEXT i
    

    베이직에서는 지표가 1에서 시작됨을 주목하라, 이것은 특이한 것이며 대부분의 언어에서는 지표가 0에서 시작한다. 배열에 대한 다른 처리방법은 없다, 여러분이 할 수 있는 것은 그것을 생성하고, 값을 할당하고 읽는것 뿐이다.

    스택 Stack

    레스토랑에서 접시들이 쌓여있는 것을 생각해 보라. 가게 점원 하나가 일단의 깨끗한 접시들을 꼭대기에 놓는다. 이것들은 하나씩 손님들에 의해서 제거된다. 스택 가장 아래에 있는 접시가 가장 나중에 사용된다.(그리고 그것밖에 없으니까!) 데이타 스택은 똑 같은 방식으로 작동한다:
    여러분은 하나의 항목을 스택으로 넣거나 하나를 꺼낸다. 꺼내어진 항목은 항상 가장 마지막에 넣어진 것이다. 이러한 스택의 속성을 일컬어 후입선출Last In First Out 혹은 리포 LIFO라고 부른다. 스택의 유용한 속석중 하나는 리스트를 스택안에 집어 넣고 다시 밖으로 꺼냄으로써 여러분이 항목의 리스트를 뒤집을 수 있다는 것이다. 결과는 처음 리스트의 반대가 될 것이다. 스택은 파이썬, Tcl 혹은 BASIC 에 내장되지 않았다. 여러분은 그런 행위를 구현하려면 약간의 프로그램코드를 작성해야 한다. 리스트가 보통 가장 좋은 출발점인데 왜냐하면 스택과 마찬가지로 그들도 필요할때 늘어날 수 있기 때문이다.

    백 Bag

    백은 어떤 특정한 순서를 가지지 않는 항목들의 집합이다. 그리고 그것은 중복도 포함할 수 있다. 백은 보통 여러분이 항목들을 찾고 제거하고 더할 수 있도록 하는 연산자를 가진다. 파이썬과 티클에서 백은 단순히 리스트이다. 베이직에서는 여러분은 거대한 배열로서 백을 구현해야 한다.

    세트 Set

    세트는 각 항목에 한개의 값만을 저장하는 특성을 지닌다. 여러분은 보통 항목이 세트에 (회원으로서) 존재하는지 점검해 볼수 있다. 항목을 더하고, 제거하고, 검색하라. 두 개의 세트를 여러가지 방식으로 수학에서의 집합이론(예를 들어 곱, 합 등등)에 대응하여 결합시켜라. 우리의 예제 언어들 중 어떤 것도 세트를 직접적으로 구현하지는 않았지만, 파이썬과 티클에서는 내장된 사전형을 사용하여 쉽게 구현될 수 있다.

    큐 Queue

    큐는 스택과 비슷하지만 큐에 먼저 들어간 항목이 또한 처음으로 나온다는 점이 다르다. 이것은 선입선출 First In First Out 혹은 피포 FIFO행태로 알려져 있다.

    다른 집합형도 얼마든지 있지만, 이것들이 여러분이 마주치게 될 중요한 것들이다. (사실 우리는 이 웹튜터에서 이러한 것들 중 약간만을 다루게 될 것이다!)

    파일 Files

    컴퓨터 사용자로서 여러분은 파일에 관한 모든 것을 안다 - 컴퓨터로 우리가 다루는 것들의 거의 기본토대이다. 그렇다면, 대부분의 프로그래밍 언어가 데이타의 특별한 파일file형을 제공한다고 해서 전혀 놀랄일이 아니다. 그렇지만 파일과 그것들을 처리하는 방법은 너무나 중요해서 나는 그것들에 대하여 논의 하는 것을 독립적인 장으로 다루게 될 때까지 이후로 연기하려고 한다.

    날짜와 시간 Dates and Times

    날짜와 시간은 프로그래밍에서 때때로 특별히 봉헌된 형태로 주어진다. 다른 때에는 그것들은 단순히 커다란 숫자로 (전형적으로 임의의 날짜/시간을 초단위로) 나타내어진다. 다른 경우에는 날짜형은 다음섹션에서 설명되는 바와 같이 복합형으로 알려져 있다. 이것은 보통 월, 일, 시간 등을 추출하기 쉽게 해준다.

    복합형/사용자 정의 Complex/User Defined

    어떤 때에는 위에 기술한 기본적인 형들이 집합형으로 결합되었을 때조차도 부적당하다. 때로 우리는 약간의 데이타 조각들을 그룹지어서 그것을 하나의 항목으로 다루기를 원한다. 주소를 기술하는 것이 적당한 예제가 될 수 있겠다:
    지번, 도로번호와 도시. 마지막으로 우편번호.

    대부분의 언어에서 여러분은 그러한 정보를 레코드record 혹은 구조 structure의 형태로 하나로 그룹지을수 있다.

    베이직에서 그러한 레코드 정의는 다음과 같다:

    Type Address
         HsNumber AS INTEGER
         Street AS STRING * 20
         Town AS STRING * 15
         ZipCode AS STRING * 7
    End Type
    

    STRING뒤의 숫자는 단순히 그 문자열의 최대 길이이다.

    파이썬에서 그것은 약간 다르다:

    >>>class Address:
    ...   def __init__(self, Hs, St, Town, Zip):
    ...     self.HsNumber = Hs
    ...     self.Street = St
    ...     self.Town = Town
    ...     self.ZipCode = Zip
    ...
    

    이것은 약간 묘하게 보이겠지만 그러나 걱정하지 마라. def __init__(...) 그리고 self이 무엇을 의미하는지는 객체지향에 관한 섹션에서 설명하겠다. 어떤 이들은 이러한 예제를 파이썬의 프롬프트에서 타이프하는데 문제가 있을수 있다. 이 장의 마지막에 여러분은 더욱 설명이 잘된 박스를 보게 될 것이다, 그러나 여러분은 단지 기다려서 원한다면 이 강좌에서 이후에 전체적인 이야기를 듣게 될 것이다. 여러분이 파이썬에 이것을 타이프해 넣으려고 한다면 여러분이 들여쓰기를 보여지는 바와 같이 복사했는지를 확인하라. 여러분이 나중에 보게 되듯이 파이썬은 들여쓰기 수준에 대하여 대단히 민감하다.

    내가 여러분이 이 모든 것들에서 인지하기를 원하는 가장 중요한 것은 우리가 몇개의 조각의 데이타를 하나의 구조로 모았다는 것이다.

    복합형에 접근하기

    우리는 복합데이타형을 변수에 역시 할당할 수 있다, 그러나 그 형의 개별적인 필드 fields에 접근하기 위해서는 우리는 어떤 특별한 접근 메카니즘을 사용해야 한다 (그것은 그 언어에 의해서 정의된다.) 보통 이것은 도트(점)이다.

    위에 우리가 정의한 주소형의 경우를 고려해 본다면 우리는 베이직에서 이렇게 할 것이다:

    DIM Addr AS Address
    Addr.HsNumber = 7
    Addr.Street = "High St"
    Addr.Town = "Anytown"
    Addr.ZipCode = "123 456"
    PRINT Addr.HsNumber," ",Addr.Street
    

    여러분이 이미 클래스정의를 위와 같이 타이프해 넣었다고 가정하고, 그리고 파이썬에서는 다음과 같다:

    Addr = Address(7,"High St","Anytown","123 456")
    print Addr.HsNumber, Addr.Street
    

    그것은 우리의 Address형의 실체를 생성한다 그리고 그것을 변수 addr에 할당한다. 우리는 그러면 새로이 생성된 실체의 Hs_NumberStreet의 필드를 점 연산자를 사용하여 출력할 수 있다. 물론, 여러분은 새로운 주소형의 변수들을 여러개 만들어 낼 수도 있다. 각각의 변수들은 자신만의 개별적인 지번과, 도로번호 등등을 가진다.

    Tcl 의 방법

    티클에서 복합형에 대해 가장 비슷하게 접근하는 것은 단순히 필드를 리스트로 저장하는 것이다. 여러분은 일련의 필드들을 다시 추출할수 있기 위하여 기억할 필요가 있다. 필드숫자를 변수에 할당함으로써, 이것은 약간 간소화 될 수 있다. 이런식으로 전술한 예제는 다음과 같이 보일 것이다:

    set Hs_num 0
    set Street 1
    set Town 2
    set zip 3
    set addr [list 7 "High St" "Anytown" "123 456"]
    puts [format "%s %s" [lindex $addr $Hs_num] [lindex $addr $Street]]
    

    티클의 형식화 문자열의 사용과 '[]'로 내포된 세트를 주목하라.

    사용자 정의 연산자

    사용자 정의형은, 어떤 언어에서는, 처리방법도 정의된다. 이것은 객체 지향형 프로그래밍 object oriented programming이라고 알려진 것의 기본토대이다. 우리는 이 주제에 관하여 전체섹션을 후에 할애 하였다. 그러나 본질적으로 객체는 데이타 요소와 그 데이타와 관련된 연산의 집합으로, 하나의 단위로 싸여져 취급되는 것이다. 파이썬은 객체를 표준라이브러리 모듈에서 광범위하게 사용하며 또한 우리가 프로그래머로서 우리 자신만의 객체형을 만들수 있도록 해준다.

    객체 연산은 사용자 정의 형의 데이타 구성원에 접근하는 것과 같은 방식으로, 점 연산자를 통하여 접근된다. 그러나 다른면으로는 함수와도 비슷하다. 이러한 특별한 함수들은 메쏘드methods라고 불리운다. 우리는 이미 이것을 리스트의 append()연산에서 보았다. 그것을 사용하기 위해서 우리는 변수이름위에 함수호출을 걸어야만 한다는 것을 상기하라:

    >>> listObject = []    # an empty list
    >>> listObject.append(42)   # a method call of the list object
    >>> print listObject
    [42]
    

    클래스라고 알려진, 객체형이 하나의 모듈에 제공되어 있다면 우리는 그 모듈을 (전에 sys모듈에 했던 것처럼) 수입해야한다. 그리고는 그 객체형을 그 모듈의 이름으로 접두사를 삼아서 실체를 생성하고 우리는 그것을 변수에 할당할 수 있다. 그러면 우리는 모듈의 이름을 사용하지 않고도 그 변수를 사용할 수 있다.

    우리는 이것을 가상적인 모듈 '고기'를 고찰함으로써 설명하려 한다. 그 모듈은 스팸클래스를 제공한다. 우리는 그 모듈을 수입하고, 스팸의 실체를 생성하고 그리고 데이타와 연산에 다음과 같이 접근한다:

    >>> import meat
    >>> mySpam = meat.Spam()  # create an instance, use module name
    >>> mySpam.slice()        # use a Spam operation
    >>> print mySpam.ingredients  # access Spam data
    {Pork:40%, Ham:45%, Fat:15%}
    

    실체를 생성할 필요가 있다는 것을 빼고는, 모듈안에 제공된 객체를 사용하는 것과 모듈안에서 발견되는 함수를 사용하는 것과는 실제적인 차이가 없다. 객체의 이름을 단순하게 함께 그룹지어진 관련된 함수와 변수들을 유지하는 라벨이라고 생각해보라.

    그것을 살펴보는 또 다른 방법은 객체는 실제 세계의 사물들을 나타내는 것이다, 우리는 프로그래머로서 그것에 대하여 처리를 할수가 있다. 이러한 관점은 프로그램에서 객체라는 원래의 아이디어가 실제 세계의 상황을 컴퓨터로 모사하려는 것으로부터 기원했다는 것이다.

    큐베이직이나 티클 모두 복합형에다 연산자를 더하는 능력을 제공하지 않는다. 그렇지만 티클에는 에드온 라이브러리가 있어서 이것을 가능하게 하며 더욱 현대화된 비쥬얼 베이직 변종은 이것을 수행한다.

    파이썬의 특별한 연산자

    이 웹튜터에서 나의 기본적인 목적은 여러분에게 프로그램하는 법을 가르치는 것이고 내가 웹튜터에서 파이썬을 사용한다고 할지라도 거기에는 특별한 이유가 있는 것은 아니며, 이것을 읽고서, 여러분은 밖으로 나가서 다른 언어를 읽고 대신에 그것을 사용할 수 있다. 실제로 그것이 바로 내가 여러분이 해주기를 바라는 것인데 어떤 언어도, 파이썬까지도, 모든 것을 할수는 없기 때문이다. 그러한 목적때문에 나는 파이썬의 모든 사양을 가르치지 않고 다른 언어에서도 역시 일반적으로 발견되는 것들에 대해서 집중적으로 다룰 것이다. 결과적으로 파이썬의 어떤 특별한 사양들에 대해서는, 그것들이 대단히 강력함에도 불구하고 나는 전혀 그것들을 설명하지 않을것이며 그것에는 특별한 연산자도 포함한다. 대부분의 프로그래밍 언어는 다른 언어에서는 지원하지 않으나 자신은 지원하는 처리방법들을 가진다. 새로운 프로그래밍 언어를 출현시키는 것은 바로 이러한 '독특한' 연산자들이다. 그리고 그것은 분명히 그 언어가 얼마나 번성하는가를 결정하는 중요한 요인이다.

    예를 들어 파이썬은 리스트 썰기( spam[X:Y] )와 터플할당( X, Y = 12, 34 )등과 같은 상대적으로 희귀한 연산들을 지원한다. 파이썬은 또한 집합의 모든 구성원들에 대하여 map()함수를 사용하여 처리를 수행하는 능력을 가진다. 많고 많은 기능이 있어서 때로는 "파이썬은 밧데리를 내장하고 나타난다"라고 말하여지곤 한다. 이러한 파이썬의 특별한 연산들이 어떻게 작동하는지에 대한 세부사항을 보려면 여러분은 파이썬 문서를 참조할 필요가 있다.

    마지막으로, 지적할 만한 사항은 내가 그 사양들이 파이썬의 특별한 것이라고 말할지라도 그것이 다른 언어에서는 발견되지 않는다는 것을 뜻하는 것이 아니고, 오히려 모든 언어에서 전부 다 발견되는 것이 아니라고 말하는 것이다. 우리가 주로 다룬 연산자들은 거의 모든 현대의 프로그래밍 언어에서는 어떤 형태로든 일반적으로 사용가능하다.

    이것으로 우리는 프로그래밍의 원 재료들을 살펴보았다, 테크닉이라는 더욱 더 흥미로운 주제로 진군해보자 그리고 어떻게 우리가 이러한 재료들을 작동하게 할수 있는지 알아보자.

    주소록 예제에 관한 더욱 상세한 정보

    내가 이전에 언급한 바와 같이, 이 예제의 세부사항은 후에 설명되겠지만, 어떤 독자들은 이 예제를 작동시키는데 어려움을 겪을 수도 있다. 이 메모장은 라인 라인단위로 그 파이썬 코드를 설명해준다:

    이 예제의 완전한 코드는 다음과 같이 보일것이다:

    >>> class Address:
    ...   def __init__(self, Hs, St, Town, Zip):
    ...     self.Hs_Number = Hs
    ...     self.Street = St
    ...     self.Town = Town
    ...     self.Zip_Code = Zip
    ...
    >>> Addr = Address(7,"High St","Anytown","123 456")
    >>> print Addr.Hs_Number, Addr.Street
    

    여기에 그 설명이 있다:

    >>> class Address:
    

    class 서술문은 파이썬에게 이경우에는 Address라고 불리우는, 새로운 형을 우리는 정의하려고 한다는 것을 말해준다. 쌍점(:)은 뒤에 따르는, 들여쓰기된 어떠한 라인도 그 클래스의 정의부분이 될 것이라는 것을 지시한다. 정의는 다음의 들여쓰기 되지 않은 라인에서 끝날 것이다. 여러분이 IDLE을 사용한다면 여러분은 그 에디터가 다음의 라인을 여러분을 위해 들여쓰기 해준다는 것을 발견할 것이다. 만약 도스창으로 명령어 라인 파이썬 프롬프트에서 작업한다면 그러면, 여러분은 보여지는 바와 같이 라인들을 수동으로 들여써줄 필요가 있을 것이다. 파이썬은 일관성만 있다면, 얼마나 많이 들여쓰기 했는냐는 상관하지 않는다.

    ...   def __init__(self, Hs, St, Town, Zip):

    우리의 클래스 안에 있는 첫번째 항목은 메쏘드 정의 method definition라고 알려진 것이다. 이 메쏘드는 __init__라고 불리는데 우리가 우리의 새로운 클래스의 실체를 생성할 때 파이썬에 의하여 수행되는 특별한 연산이다. 우리는 그것을 간단하게 알아볼 것이다. 쌍점은, 전과 같이, 다음의 들여쓰기된 라인의 세트가 그 메쏘드의 실제 정의가 될 것이라는 것이라고 단순히 파이썬에게 알려 준다.

    ...     self.Hs_Number = Hs

    이 라인과 다음의 세 라인은, 모두 값들을 우리의 객체의 내부 필드에다 할당한다. 그것들은 def 서술문으로부터 들여쓰기 되어져서 파이썬에게 그들이 __init__연산의 실제적인 정의를 구성한다는 것을 말해준다. 공백라인은 파이썬 인터프리터에게 클래스 정의가 끝났기 때문에 우리는 >>>프롬프트로 다시 돌아와야 한다는 것을 말해준다.

    >>> Addr = Address(7,"High St","Anytown","123 456")

    이것은 우리의 Address형의 새로운 실체를 만들어 주며 파이썬은 위에 정의된 __init__ 연산을 사용하여 우리가 제공한 그 값을 내부 필드에 할당한다. 그 실체는 Addr 변수에 할당된다. 마찬가지로 다른 어떤 데이타형의 실체도 그럴 수 있다.

    >>> print Addr.Hs_Number, Addr.Street

    이제 우리는 점 연산자를 사용하여 접근하여 내부필드의 값 두 개를 출력한다.

    내가 언급한 바와 같이 우리는 이 지침서에서 나중에 더 상세하게 이러한 모든 것들을 다룰 것이다. 간직해야할 중요한 요점은 파이썬으로 우리는 우리 자신만의 데이타 형을 만들수 있으며 그것들을 내장된 것들과 마찬가지로 아주 잘 사용할 수 있다는 것이다.


    기억해야할 요점
    • 데이타는 많은 형으로 나타나며 여러분이 성공적으로 수행할수 있는 연산은 여러분이 사용하고 있는 데이타의 형에 의존한다.
    • 단순한 데이타 형은 문자열, 숫자, 불리언 혹은 '진리'값을 포함한다.
    • 복합 데이타 형은 집합, 파일, 날짜와 사용자가 정의한 데이타의 형을 포함한다.
    • 모든 프로그래밍 언어에는 많은 연산자가 있고 새로운 언어를 배운다는 것은 그 언어의 데이타 형과 그러한 형에 사용가능한 연산자들에 익숙해지는 것이다.
    • (예를 들어 덧셈같은) 똑 같은 연산자가 다른 형들에 사용가능하지만, 심지어는 겉보기에 관련이 있을지라도, 그 결과는 동일하지 않을 수 있다.

    Previous  Next  Contents


    이 웹페이지에 질문이 있거나 제안사항이 있으면 다음 주소로 나에게 전자메일을 보내라: agauld@crosswinds.net