파이썬은 처음이라 – 값이란 건 처음이라

이번 글에서는 파이썬에서의 값에 대해서 살펴보겠다. 프로그래밍 언어를 배울 때에는 흔히 문법이나 알고리듬, 자료 구조와 같은 부분에 집중하면서 “값”이라는 부분, 즉 데이터 자체에 대해서는 소홀해지는 경향이 있다. 하지만 컴퓨터 프로그램은 본질적으로 데이터를 다루는 논리적인 기계장치이며, 어떤 입력값을 조작/변형처리하여 출력하는 구조를 가진다. 그 과정에서 다루어지는 값에 대한 특성을 이해하는 것은 값외의 다른 모든 것들을 이해하는 것과 같은 비중으로 중요하다.

컴퓨터에서 모든 값은 0과 1로 구성되는 이진수만이 통용된다는 것이 널리 알려져 있다. 그렇다면 어떻게 정수나 실수1, 텍스트와 같은 값들을 다룰 수 있는 것일까. 이러한 궁금증에서부터 시작하여 프로그래밍 언어에서의 값의 종류(타입)와 더불어 파이썬에서 사용되는 원시 값의 종류에 대해서 살펴보도록 하겠다.

값과 타입

컴퓨터는 전기적 신호를 통해 작동하는 기계이며, 전기신호의 ON/OFF를 구분하며, 이 ON/OFF를 조합하여 서로 다른, 즉 구분이 가능한 신호의 조합을 만들 수 있다. 이 때 ON을 1에, OFF를 0에 대응하면 일련의 ON/OFF 신호의 조합은 10110101011… 과 같은 표현으로 해석할 수 있다. 두 개의 숫자로 이루어지는 이 숫자체계를 수학에서는 이진수라고 하며, 약간의 산수를 통해서 이진수는 우리가 흔히 이해하는 10진수로 바꿔서 표시할 수 있다.

0과 1로 만들어지는 이진수는 결국 어떤 수(number)일 뿐인데, 우리가 개념적으로 사용하는 여러 가지 정보는 정확하게는 수 개념에만 한정되지 않는다. 실제로 우리는 수를 표현하기 위해서 숫자체계라는 것을 이용해서 숫자기호라는 문자를 사용한다. 사과에 오렌지를 더할 수 없듯이 “1”이라는 숫자2에 하나라는 의미의 수 1을 더할 수는 없다. 이렇 듯 우리의 관념에서도 어떤 정보는 그 타입이 구분되며, 어떤 타입들은 서로 호환되지만3 어떤 타입들은 서로 호환되지 않을 수도 있다.

정수나 float 값은 실수(Real Number[^3])라는 수 체계에서 볼 때는 같은 값이지만, 컴퓨터에서는 이진수를 사용해서 이를 표현하고 관리하기 위해서 서로 다른 기술적인 체계를 따르게 된다. 따라서 흔히 숫자라고하는 타입은 정수와 실수로 나뉘며, 보통의 프로그래밍 언어에서는 이들을 구분한다. 그외에 프로그래밍 언어에서 사용되는 가장 기초적인 데이터 타입에는 다음과 같은 것들이 있다.

  • 정수 : 0, 1, -1 과 같이 소수점 이하 자리가 없는 수. 수학에서의 정수 개념과 동일하다. 파이썬에서는 int 타입이라고 한다.
  • 실수 : 0.1, 0.5 와 같이 소수점 아래로 숫자가 있는 수. 파이썬에서는 float 이라고 한다.
  • 문자, 문자열 : 숫자 “1”, “a”, “A” 와 같이 하나의 낱자를 문자라 하며, 이러한 문자들이 1개 이상있는 단어/문장와 같은 텍스트를 문자열이라고 한다. 파이썬에서는 str 타입으로 분류한다. 특히 파이썬은 낱자와 문자열 사이에 구분이 없이 모두 str 타입을 적용한다.
  • 불리언값 : 참/거짓을 뜻하는 대수값. 보통 컴퓨터는 0을 거짓, 0이 아닌 것을 참으로 구분한다. 파이썬에는 bool 타입이라 부르며, 이 타입에는 TrueFalse 의 두 멤버만 존재한다. (참고로 각각은 대문자를 써야 한다.)
  • None : 존재하지 않음을 표현하기 위해서 “아무것도 아닌 것”을 나타내는 값이다.

이러한 기본적인 데이터 타입을 조합하여, 여러 개의 값을 하나의 단위로 묶어서 다루는 데이터 타입이 있다. 논리적으로 이들은 데이터 타입인 동시에 데이터의 구조(흔히 말하는 자료 구조)의 한 종류이기도 하다. 보통 다른 데이터들을 원소로하는 집합처럼 생각되는 타입들이다.

  • 리스트 : 순서가 있는 원소들의 집합. 파이썬에서 가장 중요한 데이터 타입 중 하나이다.
  • 튜플 : 순서가 있는 원소들의 묶음. 리스트와 혼동하기 쉬운데 단순히 하나 이상의 값을 묶어서 하나로 취급하는 용도로 사용된다.
  • 사전 : 그룹내의 고유한 이름인 키와 그 키에 대응하는 값으로 이루어지는 키값 쌍(key-value pair)들의 집합이다.
  • 집합/셋(set) : 순서가 없는 고유한 원소들의 집합.

자료 구조에 해당하는 데이터 타입은 매우 중요한데, 이 글에서 한 꼭지로 다루기에는 너무 중요하기 때문에 각각 별도의 글에서 다룰 예정이다.

숫자값들

수를 나타내는 타입으로 정수와 실수가 있다고 했다. 각각은 int 타입과 float 타입이다. 더하기, 빼기등의 산술 연산을 적용하는 값이며 가장 기본적인 수 개념들을 표현한다.

리터럴

어떤 값을 “써서 표현하는 방법”을 리터럴이라고 한다. 수를 표현하는 기본 리터럴은 다음과 같다.

  • 정수의 경우, 그냥 숫자들로 숫자값을 쓰면 된다. 0, 100, 123 과 같은 표현을 쓴다.
  • 실수의 경우, 중간에 소수점이 들어간다. 0.1,  4.2, 3.13123 와 같은 식으로 쓴다.
  • 0. 으로 시작하는 실수값에서는 흔히 앞에 시작하는 0을 뺄 수 있다. .5 는 0.5를 줄여쓴 표현이다.
  • 부호를 나타내는 – , +를 앞에 붙일 수 있다. (-1, +2.3 등)

보통 우리가 숫자를 쓰는 체계는 10진법이다. 파이썬에서는 드물게 다른 진법으로 숫자를 표현하기도 한다.

  • 기본적으로 그냥 숫자만 사용하는 경우, 이는 십진법 값으로 해석된다.
  • 파이썬이 인식할 수 있는 숫자 리터럴 체계에는 10진법외에도 이진법, 8진법, 16진법이 존재한다.
  • 이진법 숫자는 0b로 시작한다. 0b1010110 은 십진법 86을 숫자로 쓴 것이다.
  • 8진법 숫자는 0o로 시작한다. 위의 86은 8진법으로 썼을 때 0b126이다.
  • 16진법숫자는 0x로 시작한다. 16진법은 숫자외에도 a~f 까지의 문자를 포함하며, 이 글자들은 대소문자를 구분하지 않는다. 86은 16진법으로 표현시 0x56이다.

한편 큰 숫자를 다룰 때에는 _를 쓸 수 있다. 우리가 일상생활에서 큰 자리 숫자를 표현할 때 세자리마다 컴마를 찍는 것과 비슷하게 숫자 리터럴 중간에 _ 를 쓰는 것은 무시된다. 백만을 쓸 때 1_000_000 이라고 표기하면 정상적으로 1백만으로 인식되는데 1000000으로 쓰는 것보다 읽기 쉬을 수 있다. 언더스코어는 세자리마다 써야 하는 것은 아니고 원하는 아무자리에나 쓰면 된다.

숫자는 아니지만 참/ 거짓을 의미하는 부울대수값이 있다. 이들은 그 자체가 키워드로 True/False를 사용하여 표현한다.

True, False 가 키워드가 된 것은 파이썬3의 일이다. 파이썬2에서는 상수처럼 쓰이는 그냥 이름이었다. 따라서 True = False 와 같은 괴상한 구문이 아무런 문제없는 파이썬 코드였다.

연산

값을 가지고는 여러 연산을 할 수 있다. 다음은 기본적으로 지원되는 연산이다.

  • 더하기, 빼기, 곱하기, 나누기 :  각각 +, -, *, / 문자를 사용한다. 수식을 표현하는 방식은 계산기를 사용하는 방식과 똑같다.
  • 몫과 나누기 : // , % 를 사용한다.  (7 // 5, 13 % 8)
  • 거듭제곱 : ** 를 사용한다 ( 3 ** 2, 4 ** 3)
  • 비트연산 : & (and), | (or), ^ (xor), ~ (not) 이 있고, 시프트에는 << , >> 를 사용한다.
  • 비교연산 : 동등 및 대소를 비교할 수 있다.  참고로 ‘대소’비교는 ‘전후’비교가 사실은 정확한 표현이다. 비교 연산은 숫자값 뿐만 아니라 문자열에 대해서도 적용할 수 있다.
    • == , != : 같다, 같지 않다.
    • <, <=, >, >= : 작다, 작거나 같다, 크다, 크거나 같다. (좌변 기준으로)
  • 멤버십연산 : 멤버십 연산은 특정한 집합에 어떤 멤버가 속해있는지를 판단하는 것으로 비교연산에 기반을 둔다.
    • is, is not : 값의 크기가 아닌 값 자체의 정체성(identity)이 완전히 동일한지를 검사한다.
    • in, not in : 멤버십 연산. 어떠한 집합 내에 원소가 포함되는지를 검사한다. ('a' in 'apple')
  • 논리연산 : 비교 연산의 결과는 보통 참/거짓이다. 이러한 불리언값은 다음의 연산을 적용받는다. 참고로 불리언외의 타입의 값도 논리연산을 적용받을 수 있다. 논리연산을 위한 평가는 뒤에서 설명하겠다.
    • and :  두 값이 모두 참일 때 참
    • or : 한 값이 참이면 참
    • not : 단항 연산으로 우변의 값을 반전한다.

표현식

어떤 값 혹은 값들과 연산자를 함께 사용해서 수식을 표현한 것을 표현식(expression) 이라고 한다. 표현식을 평가식이라고도 하는데, 그 자체로 평가되어 하나의 결과값으로 축약된다. 따라서 1 + 1 과 같은 수식도 표현식이며, 0 과 같이 값 리터럴로 값을 표현해놓은 것 그 자체도 표현식이 될 수 있다. 이어서 소개할 문자열 역시 그 자체가 값이므로 표현식이며, 문자열과 관련되는 연산자들도 있다. 표현식은 궁극적으로 “평가”되며, 평가된다는 것은 표현식은 결국 하나의 값으로 수렴한다는 의미이다. 표현식은 간단한 수식으로 취급되고 있으나, 언어의 구조의 근간을 이루는 매우 중요한 개념이다.

앞에서 bool 타입이 아닌 숫자나 문자등의 다른 값들이 참/거짓으로 평가될 때 다음과 같이 판단된다.

  • bool : True는 참, False는 거짓이다.
  • int / float : 0이되면 거짓, 그외의 값은 참으로 평가한다.
  • str : 길이가 0인 빈 문자열은 거짓, 그외에는 참으로 평가한다.
  • 리스트, 사전 : 빈 컨테이너는 거짓, 그외에는 참으로 평가한다.
  • 임의의 객체 : None이면 거짓이며, None이 아닌 경우 값으로 평가하여 위의 규칙을 따르게 한다.

문자열

문자열은 글자 혹은 글자가 모여서 만드는 단어나 문장을 말한다. 크게는 이런 단어, 문장이 모여서 여러 줄의 단락이나 글 전체가 하나의 문자열이기도 하다.

리터럴

문자열 리터럴의 방식은 기본적으로 따옴표를 사용하는 것이다. 파이썬에서는 큰 따옴표와 작은 따옴표를 구분하지 않고 모두 문자열 리터럴에 쓴다. 하지만 괄호처럼 양쪽 따옴표가 맞아야 한다. (문자열을 둘러싸는 따옴표와 다른 따옴표는 문자열 내의 일반 글자로 해석된다. )

  • "apple" , 'apple' 은 모두 문자열 리터럴로 apple이라는 단어를 표현한 것이다.
  • 두 개의 문자열 리터럴이 공백이나 줄바꿈으로 분리되어 있는 경우에 이것은 하나의 문자열 리터럴로 해석한다. "apple,"   "banan""apple,banana"라고 쓴 표현과 동일하다.

따옴표를 세 개 연이어 쓰는 방법도 문자열 리터럴의 한 방법이다. 따옴표 세 개를 연이어서 쓰는 경우에는 문자열 내에서 줄바꿈이 그대로 허용된다. 흔히 함수나 모듈의 간단한 문서화 텍스트를 표현할 때 많이 쓰인다.

"""He said "I didn't go to 'SCHOOL' yesterday"."""  
=> He said "I didn't go to 'SCHOOL' yesterday". 를 그대로 표현할 수 있다.

=> 여러 줄에 대한 내용을 쓸 때.
'''HOMEWORK:
1. print "hello, world"
2. print even number between 2 and 12
3. calculate sum of prime numbers up to 100,000
''' 

그외에 이스케이프를 허용하지 않는 raw string 리터럴, 다른 값을 삽입하는 format string 리터럴, 바이트배열을 정의하는 bite string 리터럴등이 있는데, 조금 특수한 케이스이므로 여기서는 다루지 않겠다. (각각 r'...', f'...', b'...'와 같은 식으로 쓴다는 것 정도만 알고 넘어가자.)

연산

문자열도 엄연한 값이며, 가능한 연산이 있다.

  • 문자열 + 문자열 : 두 문자열을 연결할 수 있다.
  • 문자열 in 문자열 : 문자열 내의 특정 글자가 있는지 검사한다. ('a' in 'apple', 'c' not in 'banana')
  • 문자열 * 정수 : 문자열를 정수값만큼 반복하여 문자열을 만든다 ('abc' * 3 --> 'abcabcabc')

문자열에 실수를 곱하거나 문자열에 정수를 더하는 연산은 우리가 그냥 생각해도 어째야 할지를 모르겠고, 실제로도 정의되지 않았다. 이와 같은 연산들은 모두 ValueError 에러를 내게 되니 참고하자.

내삽 (interpolation)

내삽은 문자열에 대한 특별한 연산이다. 예를 들어 "Tom has 3 bananas and 4 apples." 라는 문자열이 있다고 할 때, 이것을 리터럴로 정의하는 것은 그 내용이 소스코드에 고정되는, 이른 바 하드 코딩(hard coding)이다. 문자열은 한 번 생성된 이후로 변경되지 않는 불변의 고정값이므로 Tom이 가지고 있는 사과나 바나나의 개수가 바뀌었을 때, 그 내용을 적절히 변경해 줄 수가 없다. 내삽(interpolation)은 문자열내에 동적으로 변할 수 있는 값을 삽입하여 상황에 따라 다른 문자열을 만드는 방법이다. 문자열 내삽의 기본원리는 문자열 내에 다른 값으로 바뀔 치환자를 준비해두고, 필요한 시점에 치환자를 실제 값의 내용으로 바꿔 문자열을 생성하는 것이다. 내삽의 방법에는 다음의 세 가지 방법이 있다.

  1. 전통적인 포맷 치환자를 사용하는 방법 : 문자열 % (값, ...)의 형식을 이용해서 문자열 내로 변수값을 밀어넣는 방법
  2. 문자열의 .format() 메소드를 사용하는 방법 : 치환자의 구분없이 사용할 수 있으며, 각 값을 포맷팅할 수 있는 장점이 있다.
  3. 문자열 포맷 리터럴을 사용하는 방법 : 포맷 메소드를 사용하지 않고 리터럴만으로 2.의 방법을 사용할 수 있다 (파이썬 3.6 이상)

전통적인 포맷 치환 방법

문자열 내에 어떤 값을 집어넣는것에 대한 필요는 아주 오래전부터 있어왔고, 이러한 치환자의 종류와 형식은 파이썬이 만들어지기 이전부터 일종의 표준으로 정의되어 자리잡고 있었다. 문자열 치환자는 퍼센트 문자 뒤에 포맷형식을 붙여서 치환자를 정의한다. 치환자를 포함하는 문자열과 각 치환자에 해당하는 값의 튜플을 (튜플을 아직 배우지는 못했지만…) % 기호로 연결하여 표현한다.

주요 치환자에는 다음과 같은 종류가 있다.

  • %d : 정수값을 나타낸다. d 앞에는 자리수와 채움문자를 넣을 수 있다. 예를 들어 %04d 라고 쓰면 앞의 0은 채움문자이고 뒤는 포맷의 폭이다. 즉 %04d 는 0으로 시작하는 네자리 정수를 의미한다. 13이라는 값을 포맷팅할 때, %d 에 치환하면 “13”이 되지만, %04d 에 치환되는 경우에는 “0013”으로 치환된다.
  • %f : 실수값을 나타낸다. f 앞에는 .3 과 같이 소수점 몇 째자리까지 표시할 것인지를 결정하는 확장정보를 넣을 수 있다. "%.3f" 라는 템플릿은 1.5를 “1.500”으로 표시해준다.
  •  그 외에 정수값은 숫자 리터럴과 같이 %b, %o, %x를 이용해서 각각 이진법, 8진법, 16진법으로 표시할 수 있다.
  • %s : 문자열을 의미한다.
  • %r : “representation”으로 타입을 구분하지 않는 값의 표현형을 말한다. 표시되고자 하는 값의 타입이 분명하지 않을 때 사용한다. 위에서 소개된 %d, %f, %s 에 대해서 올바르지 않은 타입의 값을 치환하려 하면 TypeError가 발생한다. 이럴 때 사용할 수 있다.

format 메소드를 사용하는 방법

파이썬의 기본 내장함수 중에서도 format() 함수가 있는데, 이 함수도 문자열의 format 메소드와 동일한 동작을 한다. format(문자열, 치환값)` 의 형식으로 사용하며 그외 내용은 이 절에서 설명하는 것과 동일하다.

전통적인 치환자구분이 타입을 가린다는 제약이 있고, 포맷팅의 방법이 제한되어 있다는 부분때문에 최근에 대세를 이루는 방식이다. 이 방식에서는 %d 와 같은 표현 대신에, { } 를 사용한다. { } 자체가 하나의 값을 의미하며, 번호를 부여해서 한 번 받은 값을 여러번 사용할 수 있다. 이 포맷팅 방식을 미니포맷이라고 불리는데 대략 다음과 같은 문법을 가지고 있다.

{ 치환자 }

치환자  ::= [필드이름] [!변환형] [: 포맷정의]
포맷정의 ::= [[채우기]정렬][부호][#][0][폭][그룹옵션][.소수점자리][타입]

뭔가 포맷방식이 엄청난데, 채우기와 폭은 전통적인 포맷 치환자에서도 지원하던 것인데, 왼쪽 정렬이나 중앙정렬도 설정할 수 있다. 숫자값인 경우에는 특별히 d, f, x, b, o 등의 표현타입도 정의해줄 수 있다. 이 부분을 더 깊게 파고들려면 많은 분량이 필요하므로, 앞으로 진도를 나갈 때 예제 등에서 사용하면서 설명하도록 하겠다.

None

객체의 개념에 대해서 아직 설명하기 전이라 None을 명확하게 설명하기는 어렵다. 다만 어떤 값이 없는 상태를 가리킬만한 표현이 마땅히 없기 때문에 “아무것도 없다”는 것으로 약속해놓은 어떤 값을 하나 만들어 놓은 것이다. None 이라고 대문자로 시작하도록 쓰며, 실제 출력해보아도 아무것도 출력되지 않는다. 값이 없지만 False 나 0 과는 다르기 때문에 어떤 값으로 초기화하기 어려운 경우에 쓰기도 한다.

 

정리

이상으로 가장 기본적인 파이썬의 값 타입들에 대해서 살펴보았다. 물론 리스트와 사전, 그리고 튜플과 같은 다른 타입들이 있지만, 분량 관계상 이 글에서 계속 다루는 것 보다는 이쯤에서 한 번 끊고 가는 것이 좋겠다. 계속해서 다음 포스팅으로 이어나가시라….


  1. floating number. 0.5와 같이 소수점 이하 자리를 갖는 수를 말한다. 
  2. 이 글에서는 관례를 따라 숫자값을 표현할 때는 숫자만 쓰고, 문자 자체를 표현할 때는 따옴표를 적용할 것이다. 
  3. 1 + 0.5 를 계산할 수 있듯이 정수와 실수는 몇 가지 연산에서 호환이 가능하다. 이 타입간 호환은 사용하는 프로그래밍 언어에 따라 제약이 있을 수 있다.