1. 개요

1. 개요 (Introduction)

이 참조 매뉴얼은 Python 프로그래밍 언어를 설명해요. 튜토리얼이라기보다 언어 사양서에 가깝답니다.

출처: 1. Introduction

본문

이 참조 매뉴얼은 Python 프로그래밍 언어를 설명해요. 튜토리얼로 쓰인 문서는 아니랍니다.

가능한 한 정확하게 쓰려고 노력했지만, 문법(syntax)과 어휘 분석(lexical analysis)을 제외한 모든 부분은 형식 사양 대신 영어로 설명하기로 했어요. 이렇게 하면 일반 독자들이 문서를 더 쉽게 이해할 수 있지만, 그만큼 모호함이 남을 수 있답니다. 그래서 화성에서 온 사람이 이 문서만 보고 Python을 다시 구현하려 한다면 여러 가지를 추측해야 할 테고, 실제로는 꽤 다른 언어를 만들게 될지도 몰라요. 반대로 Python을 쓰면서 특정 언어 영역의 정확한 규칙이 궁금하다면, 여기에서 분명히 찾을 수 있을 거예요. 언어의 더 형식적인 정의를 보고 싶다면, 시간을 내어 기여해 주시거나 복제 기계를 발명해 보세요 :-).

언어 참조 문서에 구현 세부 사항을 너무 많이 추가하는 것은 위험해요. 구현이 바뀔 수도 있고, 같은 언어의 다른 구현이 다르게 동작할 수도 있으니까요. 다만 CPython은 널리 쓰이는 유일한 Python 구현이고(대안 구현들도 계속 지지를 얻고 있긴 하지만), CPython만의 특이한 동작들은 특히 구현이 추가적인 제약을 부과하는 경우 언급할 가치가 있답니다. 그래서 문서 곳곳에 짧은 "구현 참고(implementation notes)"를 넣어 두었어요.

모든 Python 구현에는 여러 내장 모듈과 표준 모듈이 함께 제공돼요. 이들은 Python 표준 라이브러리 문서에 정리되어 있답니다. 언어 정의와 의미 있게 상호작용하는 몇몇 내장 모듈은 이 문서에서 언급하기도 해요.

1.1. 대안 구현 (Alternate Implementations)

단연 가장 인기 있는 Python 구현이 하나 있긴 하지만, 서로 다른 독자층이 관심을 가질 만한 대안 구현들도 몇 가지 있어요.

알려진 구현들로는 다음이 있어요:

  • CPython: C로 작성된, 원조이자 가장 꾸준히 관리되는 Python 구현이에요. 새로운 언어 기능은 일반적으로 여기에서 먼저 등장한답니다.

  • Jython: Java로 구현된 Python이에요. 이 구현은 Java 애플리케이션용 스크립트 언어로 쓰거나, Java 클래스 라이브러리를 사용해 애플리케이션을 만드는 데 쓸 수 있어요. Java 라이브러리용 테스트를 만드는 데도 자주 사용된답니다. 자세한 정보는 Jython 웹사이트에서 확인할 수 있어요.

  • Python for .NET: 이 구현은 실제로 CPython 구현을 사용하지만, 관리되는 .NET 애플리케이션이라 .NET 라이브러리를 사용할 수 있게 해줘요. Brian Lloyd가 만들었답니다. 자세한 내용은 Python for .NET 홈 페이지를 참고하세요.

  • IronPython: .NET용 대안 Python이에요. Python.NET과 달리, IL을 생성하고 Python 코드를 .NET 어셈블리로 직접 컴파일하는 완전한 Python 구현이랍니다. Jython의 원조 창시자인 Jim Hugunin이 만들었어요. 자세한 내용은 IronPython 웹사이트를 참고하세요.

  • PyPy: Python으로 완전히 작성된 Python 구현이에요. 스택리스(stackless) 지원이나 JIT(Just in Time) 컴파일러처럼 다른 구현에는 없는 몇 가지 고급 기능을 지원한답니다. 이 프로젝트의 목표 중 하나는 (Python으로 작성되어 있으므로) 인터프리터를 수정하기 쉽게 만들어 언어 자체에 대한 실험을 장려하는 거예요. 추가 정보는 PyPy 프로젝트 홈 페이지에서 확인할 수 있어요.

이 구현들은 각각 이 매뉴얼에 문서화된 언어와 어떤 식으로든 다르거나, 표준 Python 문서에서 다루는 내용을 넘어서는 특정 정보를 제공하기도 해요. 여러분이 사용하는 특정 구현에 대해 더 알아야 할 것이 있다면 해당 구현별 문서를 참고하시기 바래요.

1.2. 표기법 (Notation)

어휘 분석과 문법 설명은 EBNF와 PEG를 혼합한 문법 표기법을 사용해요. 예를 들어:

**name**:   `letter` (`letter` | `digit` | "_")*
**letter**: "a"..."z" | "A"..."Z"
**digit**:  "0"..."9"

이 예에서 첫 줄은 nameletter 뒤에 0개 이상의 letter, digit, 밑줄(underscore)의 연속이 따라오는 것임을 말해요. letter는 다시 'a'부터 'z', A부터 Z까지의 단일 문자 중 하나이고, digit0부터 9까지의 단일 문자랍니다.

각 규칙은 정의되는 규칙을 식별하는 이름으로 시작하고, 그 뒤에 콜론 :이 따라와요. 콜론 오른쪽의 정의는 다음 문법 요소들을 사용해요:

  • name: 이름은 다른 규칙을 가리켜요. 가능하면 해당 규칙 정의로의 링크예요.
  • TOKEN: 대문자 이름은 토큰을 가리켜요. 문법 정의에서 토큰은 규칙과 동일하게 취급돼요.
  • "text", 'text': 작은따옴표나 큰따옴표로 묶인 텍스트는 (따옴표 없이) 문자 그대로 일치해야 해요. 따옴표의 종류는 text의 의미에 따라 선택돼요:
    • 'if': 작은따옴표로 묶인 이름은 키워드(keyword)를 나타내요.
    • "case": 큰따옴표로 묶인 이름은 소프트 키워드(soft-keyword)를 나타내요.
    • '@': 작은따옴표로 묶인 비문자 기호는 OP 토큰, 즉 구분 기호(delimiter)나 연산자(operator)를 나타내요.
  • e1 e2: 공백(whitespace)으로만 구분된 항목들은 연속(sequence)을 나타내요. 여기서 e1 뒤에는 e2가 반드시 따라와야 해요.
  • e1 | e2: 세로 막대는 대안(alternatives)을 구분하는 데 쓰여요. PEG의 "순서 선택(ordered choice)"을 나타내는데, e1이 일치하면 e2는 고려되지 않아요. 전통적인 PEG 문법에서는 세로 막대 대신 슬래시 /로 표기해요. 배경과 세부 사항은 PEP 617을 참고하세요.
  • e*: 별표는 앞 항목이 0회 이상 반복됨을 뜻해요.
  • e+: 마찬가지로 더하기는 1회 이상 반복을 뜻해요.
  • [e]: 대괄호로 묶인 구문은 0회 또는 1회 발생을 뜻해요. 다시 말해, 묶인 구문은 선택적(optional)이에요.
  • e?: 물음표는 대괄호와 정확히 같은 의미를 가져요. 앞 항목이 선택적이라는 뜻이에요.
  • (e): 괄호는 그룹화에 쓰여요.

다음 표기법은 어휘 정의에서만 사용돼요:

  • "a"..."z": 세 점으로 구분된 두 개의 리터럴 문자는 주어진 (포함하는) ASCII 문자 범위에서 단일 문자 하나를 선택함을 뜻해요.
  • <...>: 꺾쇠괄호 사이의 구문은 일치되는 기호에 대한 비공식적인 설명(예: <any ASCII character except "\">)이거나, 인근 텍스트에서 정의된 약어(예: <Lu>)를 나타내요.

일부 정의는 lookahead(전방 탐색)도 사용해요. 이는 어떤 요소가 주어진 위치에서 일치해야(또는 일치하지 않아야) 하지만 입력을 소비하지는 않음을 나타내요:

  • &e: 양의 lookahead(즉 e가 일치해야 함)
  • !e: 음의 lookahead(즉 e가 일치하지 않아야 함)

단항 연산자(*, +, ?)는 가능한 한 가장 강하게 결합하고, 세로 막대(|)는 가장 약하게 결합해요.

공백은 토큰을 구분하는 데에만 의미가 있어요.

규칙은 보통 한 줄에 담기지만, 너무 긴 규칙은 줄바꿈될 수 있어요:

**literal**: stringliteral | bytesliteral
         | integer | floatnumber | imagnumber

또는 규칙을 첫 줄이 콜론에서 끝나고 각 대안이 새 줄의 세로 막대에서 시작하도록 서식화할 수도 있어요. 예를 들어:

**literal**:
   | stringliteral
   | bytesliteral
   | integer
   | floatnumber
   | imagnumber

이것이 빈 첫 번째 대안이 있다는 뜻은 아니에요.

1.2.1. 어휘 및 구문 정의 (Lexical and Syntactic definitions)

어휘(lexical) 분석과 구문(syntactic) 분석 사이에는 차이가 있어요. 어휘 분석기는 입력 소스의 개별 문자들을 다루는 반면, *파서(parser)*는 어휘 분석이 만들어낸 토큰 스트림을 다루는 구문 분석기랍니다. 다만 어떤 경우 두 단계 사이의 정확한 경계는 CPython 구현 세부 사항이에요.

둘 사이의 실질적인 차이는 어휘 정의에서는 모든 공백이 유의미하다는 점이에요. 어휘 분석기는 token.INDENTNEWLINE 같은 토큰으로 변환되지 않는 공백은 모두 버려요. 그런 다음 구문 정의는 소스 문자 대신 이 토큰들을 사용한답니다.

이 문서는 두 스타일의 정의에 모두 동일한 BNF 문법을 사용해요. 다음 장(어휘 분석)에서 쓰이는 BNF는 모두 어휘 정의이고, 이후 장에서 쓰이는 것은 구문 정의랍니다.

더 알아보기 (Learn more)