1. Giới thiệu

Tài liệu tham khảo này mô tả ngôn ngữ lập trình Python. Nó không nhằm mục đích hướng dẫn.

Trong khi tôi đang cố gắng chính xác nhất có thể, tôi đã chọn sử dụng tiếng Anh thay vì các thông số kỹ thuật chính thức cho mọi thứ ngoại trừ phân tích cú pháp và từ vựng. Điều này sẽ làm cho tài liệu dễ hiểu hơn đối với người đọc bình thường, nhưng sẽ có chỗ cho sự mơ hồ. Do đó, nếu bạn đến từ sao Hỏa và cố gắng triển khai lại Python chỉ từ tài liệu này, bạn có thể phải đoán mọi thứ và trên thực tế, bạn có thể sẽ triển khai một ngôn ngữ hoàn toàn khác. Mặt khác, nếu bạn đang sử dụng Python và thắc mắc các quy tắc chính xác về một lĩnh vực ngôn ngữ cụ thể là gì, bạn chắc chắn có thể tìm thấy chúng ở đây. Nếu bạn muốn xem một định nghĩa chính thức hơn về ngôn ngữ, có thể bạn có thể tình nguyện dành thời gian của mình --- hoặc phát minh ra máy nhân bản :-).

Thật nguy hiểm khi thêm quá nhiều chi tiết triển khai vào tài liệu tham chiếu ngôn ngữ --- việc triển khai có thể thay đổi và các triển khai khác của cùng một ngôn ngữ có thể hoạt động khác nhau. Mặt khác, CPython là một triển khai Python được sử dụng rộng rãi (mặc dù các triển khai thay thế tiếp tục nhận được sự hỗ trợ) và những điểm kỳ quặc cụ thể của nó đôi khi đáng được đề cập, đặc biệt là khi việc triển khai áp đặt các hạn chế bổ sung. Vì vậy, bạn sẽ thấy những “ghi chú thực hiện” ngắn rải rác khắp văn bản.

Mọi triển khai Python đều đi kèm với một số mô-đun tiêu chuẩn và tích hợp sẵn. Đây là tài liệu trong Thư viện chuẩn Python. Một số mô-đun tích hợp được đề cập khi chúng tương tác một cách đáng kể với định nghĩa ngôn ngữ.

1.1. Triển khai thay thế

Mặc dù có một triển khai Python phổ biến nhất cho đến nay, nhưng vẫn có một số triển khai thay thế được các đối tượng khác nhau đặc biệt quan tâm.

Các triển khai đã biết bao gồm:

CPython

Đây là bản triển khai Python nguyên bản và được bảo trì nhiều nhất, được viết bằng C. Các tính năng ngôn ngữ mới thường xuất hiện ở đây đầu tiên.

Jython

Python được triển khai bằng Java. Việc triển khai này có thể được sử dụng làm ngôn ngữ kịch bản cho các ứng dụng Java hoặc có thể được sử dụng để tạo các ứng dụng sử dụng thư viện lớp Java. Nó cũng thường được sử dụng để tạo các bài kiểm tra cho các thư viện Java. Thông tin thêm có thể được tìm thấy tại the Jython website.

Python cho .NET

Việc triển khai này thực sự sử dụng triển khai CPython nhưng là một ứng dụng .NET được quản lý và cung cấp các thư viện .NET. Nó được tạo ra bởi Brian Lloyd. Để biết thêm thông tin, hãy xem Python for .NET home page.

SắtPython

Một Python thay thế cho .NET. Không giống như Python.NET, đây là một triển khai Python hoàn chỉnh giúp tạo IL và biên dịch mã Python trực tiếp thành các tập hợp .NET. Nó được tạo ra bởi Jim Hugunin, người sáng tạo ban đầu của Jython. Để biết thêm thông tin, xem the IronPython website.

PyPy

Việc triển khai Python được viết hoàn toàn bằng Python. Nó hỗ trợ một số tính năng nâng cao không có trong các triển khai khác như hỗ trợ không xếp chồng và trình biên dịch Just in Time. Một trong những mục tiêu của dự án là khuyến khích thử nghiệm với chính ngôn ngữ đó bằng cách làm cho việc sửa đổi trình thông dịch trở nên dễ dàng hơn (vì nó được viết bằng Python). Thông tin bổ sung có sẵn trên the PyPy project's home page.

Mỗi cách triển khai này khác nhau theo một cách nào đó so với ngôn ngữ được ghi trong tài liệu hướng dẫn này hoặc giới thiệu thông tin cụ thể ngoài những gì được đề cập trong tài liệu Python tiêu chuẩn. Vui lòng tham khảo tài liệu dành riêng cho việc triển khai để xác định những điều khác bạn cần biết về cách triển khai cụ thể mà bạn đang sử dụng.

1.2. Ký hiệu

Các mô tả về phân tích từ vựng và cú pháp sử dụng ký hiệu ngữ pháp là sự kết hợp của EBNFPEG. Ví dụ:

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

Trong ví dụ này, dòng đầu tiên nói rằng nameletter, theo sau là một chuỗi gồm 0 hoặc nhiều letters, digits và dấu gạch dưới. Lần lượt, letter là bất kỳ ký tự đơn nào từ 'a' đến 'z'A đến Z; digit là một ký tự đơn từ 0 đến 9.

Mỗi quy tắc bắt đầu bằng một tên (xác định quy tắc đang được xác định), theo sau là dấu hai chấm, :. Định nghĩa ở bên phải dấu hai chấm sử dụng các thành phần cú pháp sau:

  • name: Một tên đề cập đến một quy tắc khác. Nếu có thể, đó là một liên kết đến định nghĩa của quy tắc.

    • TOKEN: Tên viết hoa đề cập đến token. Đối với mục đích định nghĩa ngữ pháp, mã thông báo cũng giống như quy tắc.

  • "text", 'text': Văn bản trong dấu ngoặc đơn hoặc dấu ngoặc kép phải khớp theo nghĩa đen (không có dấu ngoặc kép). Kiểu trích dẫn được chọn theo ý nghĩa của text:

    • 'if': Tên trong dấu ngoặc đơn biểu thị keyword.

    • "case": Tên trong dấu ngoặc kép biểu thị soft-keyword.

    • '@': Ký hiệu không phải chữ cái trong dấu ngoặc đơn biểu thị mã thông báo OP, nghĩa là delimiter hoặc operator.

  • e1 e2: Các mục chỉ được phân tách bằng khoảng trắng biểu thị một chuỗi. Ở đây, e1 phải được theo sau bởi e2.

  • e1 | e2: Thanh dọc dùng để phân tách các lựa chọn thay thế. Nó biểu thị "lựa chọn có thứ tự" của PEG: nếu e1 khớp, e2 không được xem xét. Trong ngữ pháp PEG truyền thống, chữ này được viết dưới dạng dấu gạch chéo, /, thay vì thanh dọc. Xem PEP 617 để biết thêm thông tin cơ bản và chi tiết.

  • e*: Một ngôi sao có nghĩa là không có hoặc nhiều lần lặp lại mục trước đó.

  • e+: Tương tự, dấu cộng có nghĩa là một hoặc nhiều lần lặp lại.

  • [e]: Cụm từ nằm trong dấu ngoặc vuông có nghĩa là không hoặc một lần xuất hiện. Nói cách khác, cụm từ kèm theo là tùy chọn.

  • e?: Dấu hỏi có ý nghĩa giống hệt như dấu ngoặc vuông: mục trước là tùy chọn.

  • (e): Dấu ngoặc đơn được sử dụng để nhóm.

Ký hiệu sau đây chỉ được sử dụng trong lexical definitions.

  • "a"..."z": Hai ký tự chữ cách nhau bằng ba dấu chấm có nghĩa là sự lựa chọn của bất kỳ ký tự đơn nào trong phạm vi (bao gồm) nhất định của các ký tự ASCII.

  • <...>: Cụm từ nằm giữa dấu ngoặc nhọn cung cấp mô tả không chính thức về ký hiệu trùng khớp (ví dụ: <any ASCII character except "\">) hoặc một từ viết tắt được xác định trong văn bản gần đó (ví dụ: <Lu>).

Một số định nghĩa cũng sử dụng lookaheads, chỉ ra rằng một phần tử phải (hoặc không được) khớp ở một vị trí nhất định, nhưng không tiêu tốn bất kỳ đầu vào nào:

  • &e: một cái nhìn tích cực (nghĩa là cần phải có e để phù hợp)

  • !e: một cái nhìn tiêu cực (nghĩa là e bắt buộc phải có not để khớp)

Các toán tử đơn nguyên (*, +, ?) liên kết chặt chẽ nhất có thể; thanh dọc (|) liên kết lỏng lẻo nhất.

Khoảng trắng chỉ có ý nghĩa để phân tách các mã thông báo.

Các quy tắc thường được chứa trên một dòng, nhưng các quy tắc quá dài có thể được gói lại:

literal: stringliteral | bytesliteral
         | integer | floatnumber | imagnumber

Ngoài ra, các quy tắc có thể được định dạng bằng dòng đầu tiên kết thúc bằng dấu hai chấm và mỗi quy tắc thay thế bắt đầu bằng một thanh dọc trên một dòng mới. Ví dụ:

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

Điều này not có nghĩa là có một lựa chọn thay thế đầu tiên trống.

1.2.1. Định nghĩa từ vựng và cú pháp

Có một số khác biệt giữa phân tích lexicalsyntactic: lexical analyzer hoạt động trên các ký tự riêng lẻ của nguồn đầu vào, trong khi parser (bộ phân tích cú pháp) hoạt động trên luồng tokens được tạo bởi phân tích từ vựng. Tuy nhiên, trong một số trường hợp, ranh giới chính xác giữa hai giai đoạn là chi tiết triển khai CPython.

Sự khác biệt thực tế giữa hai loại này là trong định nghĩa lexical, tất cả khoảng trắng đều có ý nghĩa. Trình phân tích từ vựng discards tất cả khoảng trắng không được chuyển đổi thành mã thông báo như token.INDENT hoặc NEWLINE. Các định nghĩa Syntactic sau đó sử dụng các mã thông báo này thay vì các ký tự nguồn.

Tài liệu này sử dụng cùng một ngữ pháp BNF cho cả hai kiểu định nghĩa. Tất cả việc sử dụng BNF trong chương tiếp theo (Phân tích từ vựng) đều là định nghĩa từ vựng; cách sử dụng trong các chương tiếp theo là định nghĩa cú pháp.