7. câu lệnh đơn giản

Một câu lệnh đơn giản được bao gồm trong một dòng logic duy nhất. Một số câu lệnh đơn giản có thể xuất hiện trên một dòng, cách nhau bằng dấu chấm phẩy. Cú pháp cho các câu lệnh đơn giản là:

simple_stmt: expression_stmt
             | assert_stmt
             | assignment_stmt
             | augmented_assignment_stmt
             | annotated_assignment_stmt
             | pass_stmt
             | del_stmt
             | return_stmt
             | yield_stmt
             | raise_stmt
             | break_stmt
             | continue_stmt
             | import_stmt
             | future_stmt
             | global_stmt
             | nonlocal_stmt
             | type_stmt

7.1. Câu lệnh biểu thức

Các câu lệnh biểu thức được sử dụng (chủ yếu là tương tác) để tính toán và ghi một giá trị hoặc (thường) để gọi một thủ tục (một hàm không trả về kết quả có ý nghĩa; trong Python, các thủ tục trả về giá trị None). Việc sử dụng các câu lệnh biểu thức khác được cho phép và đôi khi hữu ích. Cú pháp cho một câu lệnh biểu thức là:

expression_stmt: starred_expression

Một câu lệnh biểu thức đánh giá danh sách biểu thức (có thể là một biểu thức đơn lẻ).

Trong chế độ tương tác, nếu giá trị không phải là None thì nó sẽ được chuyển đổi thành một chuỗi bằng cách sử dụng hàm repr() tích hợp và chuỗi kết quả sẽ được ghi vào đầu ra tiêu chuẩn trên một dòng (ngoại trừ nếu kết quả là None, do đó lệnh gọi thủ tục đó không gây ra bất kỳ đầu ra nào.)

7.2. Báo cáo bài tập

Câu lệnh gán được sử dụng để (lại) liên kết tên với các giá trị và sửa đổi các thuộc tính hoặc mục của các đối tượng có thể thay đổi:

assignment_stmt: (target_list "=")+ (starred_expression | yield_expression)
target_list:     target ("," target)* [","]
target:          identifier
                 | "(" [target_list] ")"
                 | "[" [target_list] "]"
                 | attributeref
                 | subscription
                 | "*" target

(Xem phần bầu cử sơ bộ để biết định nghĩa cú pháp cho attributerefsubscription.)

Câu lệnh gán đánh giá danh sách biểu thức (hãy nhớ rằng đây có thể là một biểu thức đơn hoặc một danh sách được phân tách bằng dấu phẩy, danh sách sau tạo ra một bộ dữ liệu) và gán đối tượng kết quả duy nhất cho mỗi danh sách đích, từ trái sang phải.

Phép gán được xác định đệ quy tùy thuộc vào dạng của mục tiêu (danh sách). Khi mục tiêu là một phần của đối tượng có thể thay đổi (tham chiếu thuộc tính hoặc đăng ký), đối tượng có thể thay đổi cuối cùng phải thực hiện phép gán và quyết định về tính hợp lệ của nó, đồng thời có thể đưa ra một ngoại lệ nếu việc gán không được chấp nhận. Các quy tắc được tuân theo bởi nhiều loại khác nhau và các ngoại lệ được nêu ra được đưa ra cùng với định nghĩa về các loại đối tượng (xem phần Hệ thống phân cấp loại tiêu chuẩn).

Việc gán một đối tượng vào danh sách đích, tùy ý đặt trong dấu ngoặc đơn hoặc dấu ngoặc vuông, được định nghĩa đệ quy như sau.

  • Nếu danh sách mục tiêu là một mục tiêu duy nhất không có dấu phẩy ở cuối, tùy chọn trong dấu ngoặc đơn, đối tượng sẽ được gán cho mục tiêu đó.

  • Khác:

    • Nếu danh sách mục tiêu chứa một mục tiêu có tiền tố dấu hoa thị, được gọi là mục tiêu "được gắn dấu sao": Đối tượng phải là một mục tiêu có thể lặp lại với ít nhất nhiều mục bằng số mục tiêu trong danh sách mục tiêu, trừ đi một mục. Các mục đầu tiên của vòng lặp được gán, từ trái sang phải, cho các mục tiêu trước mục tiêu được gắn dấu sao. Các mục cuối cùng của vòng lặp được gán cho các mục tiêu sau mục tiêu được gắn dấu sao. Sau đó, danh sách các mục còn lại trong vòng lặp sẽ được gán cho mục tiêu được gắn dấu sao (danh sách có thể trống).

    • Khác: Đối tượng phải là một đối tượng có thể lặp lại với cùng số lượng mục như có các mục tiêu trong danh sách mục tiêu và các mục được gán, từ trái sang phải, cho các mục tiêu tương ứng.

Việc gán một đối tượng cho một mục tiêu duy nhất được xác định đệ quy như sau.

  • Nếu mục tiêu là một mã định danh (tên):

    • Nếu tên không xuất hiện trong câu lệnh global hoặc nonlocal trong khối mã hiện tại: tên đó được liên kết với đối tượng trong không gian tên cục bộ hiện tại.

    • Mặt khác: tên được liên kết với đối tượng trong không gian tên chung hoặc không gian tên bên ngoài được xác định tương ứng bởi nonlocal.

    Tên sẽ được phục hồi nếu nó đã bị ràng buộc. Điều này có thể khiến số tham chiếu của đối tượng trước đó được liên kết với tên đạt tới 0, khiến đối tượng bị hủy phân bổ và hàm hủy của nó (nếu có) được gọi.

  • Nếu mục tiêu là tham chiếu thuộc tính: Biểu thức chính trong tham chiếu được đánh giá. Nó sẽ mang lại một đối tượng với các thuộc tính có thể gán được; nếu không đúng như vậy, TypeError sẽ được nâng lên. Đối tượng đó sau đó được yêu cầu gán đối tượng được gán cho thuộc tính đã cho; nếu nó không thể thực hiện nhiệm vụ, nó sẽ đưa ra một ngoại lệ (thường nhưng không nhất thiết là AttributeError).

    Lưu ý: Nếu đối tượng là một phiên bản lớp và tham chiếu thuộc tính xuất hiện ở cả hai phía của toán tử gán, biểu thức bên phải, a.x có thể truy cập thuộc tính phiên bản hoặc (nếu không tồn tại thuộc tính phiên bản) thuộc tính lớp. Mục tiêu bên trái a.x luôn được đặt làm thuộc tính phiên bản, tạo nó nếu cần. Do đó, hai lần xuất hiện của a.x không nhất thiết phải đề cập đến cùng một thuộc tính: nếu biểu thức bên phải đề cập đến một thuộc tính lớp, thì phía bên trái sẽ tạo một thuộc tính phiên bản mới làm mục tiêu của phép gán:

    lớp Cl:
        x = 3 # class biến
    inst = Cls()
    inst.x = inst.x + 1 # writes inst.x là 4 để lại Cls.x là 3
    

    Mô tả này không nhất thiết phải áp dụng cho các thuộc tính mô tả, chẳng hạn như các thuộc tính được tạo bằng property().

  • Nếu mục tiêu là đăng ký: Biểu thức chính trong tham chiếu sẽ được đánh giá. Tiếp theo, biểu thức chỉ số dưới được đánh giá. Sau đó, phương thức __setitem__() của chính được gọi với hai đối số: chỉ số dưới và đối tượng được gán.

    Thông thường, __setitem__() được xác định trên các đối tượng chuỗi có thể thay đổi (chẳng hạn như danh sách) và các đối tượng ánh xạ (chẳng hạn như từ điển) và hoạt động như sau.

    Nếu giá trị chính là một đối tượng chuỗi có thể thay đổi (chẳng hạn như danh sách), thì chỉ số dưới phải mang lại một số nguyên. Nếu nó âm, độ dài của chuỗi sẽ được thêm vào nó. Giá trị kết quả phải là số nguyên không âm nhỏ hơn độ dài của chuỗi và chuỗi được yêu cầu gán đối tượng được gán cho mục của nó với chỉ mục đó. Nếu chỉ mục nằm ngoài phạm vi, IndexError sẽ được nâng lên (việc gán cho một chuỗi được chỉ số dưới không thể thêm các mục mới vào danh sách).

    Nếu chính là một đối tượng ánh xạ (chẳng hạn như từ điển), thì chỉ số dưới phải có loại tương thích với loại khóa của ánh xạ và sau đó, ánh xạ sẽ được yêu cầu tạo một cặp khóa/giá trị để ánh xạ chỉ số dưới tới đối tượng được chỉ định. Điều này có thể thay thế cặp khóa/giá trị hiện có bằng cùng một giá trị khóa hoặc chèn một cặp khóa/giá trị mới (nếu không tồn tại khóa có cùng giá trị).

    Nếu mục tiêu là một phần cắt: Biểu thức chính sẽ đánh giá một đối tượng chuỗi có thể thay đổi (chẳng hạn như danh sách). Đối tượng được chỉ định phải là iterable. Giới hạn dưới và giới hạn trên của phần cắt phải là số nguyên; nếu chúng là None (hoặc không có), giá trị mặc định là 0 và độ dài của chuỗi. Nếu một trong hai giới hạn là âm thì độ dài của chuỗi sẽ được thêm vào đó. Các giới hạn kết quả được cắt bớt để nằm giữa 0 và độ dài của chuỗi. Cuối cùng, đối tượng chuỗi được yêu cầu thay thế lát cắt bằng các mục của chuỗi được chỉ định. Độ dài của lát cắt có thể khác với độ dài của chuỗi được chỉ định, do đó sẽ thay đổi độ dài của chuỗi mục tiêu nếu chuỗi mục tiêu cho phép.

Mặc dù định nghĩa về phép gán ngụ ý rằng sự trùng lặp giữa vế trái và vế phải là 'đồng thời' (ví dụ: a, b = b, a hoán đổi hai biến), sự chồng chéo within việc tập hợp các biến được gán cho xảy ra từ trái sang phải, đôi khi dẫn đến nhầm lẫn. Ví dụ: chương trình sau in [0, 2]:

x = [0, 1]
tôi = 0
i, x[i] = 1, 2 # i được cập nhật thì x[i] được cập nhật
in(x)

Xem thêm

PEP 3132 - Giải nén lặp lại mở rộng

Thông số kỹ thuật cho tính năng *target.

7.2.1. Báo cáo bài tập tăng cường

Phép gán tăng cường là sự kết hợp, trong một câu lệnh, của một phép toán nhị phân và một câu lệnh gán:

augmented_assignment_stmt: augtarget augop (expression_list | yield_expression)
augtarget:                 identifier | attributeref | subscription
augop:                     "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**="
                           | ">>=" | "<<=" | "&=" | "^=" | "|="

(Xem phần bầu cử sơ bộ để biết định nghĩa cú pháp của ba ký hiệu cuối cùng.)

Phép gán tăng cường đánh giá mục tiêu (không giống như các câu lệnh gán thông thường, không thể giải nén) và danh sách biểu thức, thực hiện thao tác nhị phân cụ thể cho loại phép gán trên hai toán hạng và gán kết quả cho mục tiêu ban đầu. Mục tiêu chỉ được đánh giá một lần.

Một câu lệnh gán tăng cường như x += 1 có thể được viết lại thành x = x + 1 để đạt được hiệu quả tương tự nhưng không hoàn toàn bằng nhau. Trong phiên bản mở rộng, x chỉ được đánh giá một lần. Ngoài ra, khi có thể, thao tác thực tế được thực hiện in-place, nghĩa là thay vì tạo một đối tượng mới và gán đối tượng đó cho mục tiêu, đối tượng cũ sẽ được sửa đổi.

Không giống như các bài tập thông thường, các bài tập tăng cường đánh giá phía bên trái before đánh giá phía bên phải. Ví dụ: a[i] += f(x) trước tiên tra cứu a[i], sau đó nó đánh giá f(x) và thực hiện phép cộng, và cuối cùng, nó ghi kết quả trở lại a[i].

Ngoại trừ việc gán cho các bộ dữ liệu và nhiều mục tiêu trong một câu lệnh, phép gán được thực hiện bằng các câu lệnh gán tăng cường được xử lý giống như các phép gán thông thường. Tương tự, ngoại trừ hành vi in-place có thể xảy ra, phép toán nhị phân được thực hiện bằng phép gán tăng cường cũng giống như các phép toán nhị phân thông thường.

Đối với các mục tiêu là tham chiếu thuộc tính, caveat about class and instance attributes tương tự sẽ được áp dụng như đối với các phép gán thông thường.

7.2.2. Báo cáo bài tập có chú thích

Phép gán Annotation là sự kết hợp, trong một câu lệnh, của một chú thích biến hoặc thuộc tính và một câu lệnh gán tùy chọn:

annotated_assignment_stmt: augtarget ":" expression
                           ["=" (starred_expression | yield_expression)]

Sự khác biệt so với Báo cáo bài tập bình thường là chỉ cho phép một mục tiêu duy nhất.

Mục tiêu gán được coi là "đơn giản" nếu nó bao gồm một tên duy nhất không nằm trong dấu ngoặc đơn. Đối với các mục tiêu gán đơn giản, nếu ở phạm vi lớp hoặc mô-đun, các chú thích được tập hợp trong annotation scope được đánh giá một cách lười biếng. Các chú thích có thể được đánh giá bằng cách sử dụng thuộc tính __annotations__ của một lớp hoặc mô-đun hoặc sử dụng các tiện ích trong mô-đun annotationlib.

Nếu mục tiêu gán không đơn giản (thuộc tính, nút chỉ số dưới hoặc tên được đặt trong ngoặc đơn), thì chú thích sẽ không bao giờ được đánh giá.

Nếu một tên được chú thích trong phạm vi hàm thì tên này là tên cục bộ cho phạm vi đó. Chú thích không bao giờ được đánh giá và lưu trữ trong phạm vi chức năng.

Nếu có phía bên phải, phép gán có chú thích sẽ thực hiện phép gán thực tế như thể không có chú thích nào. Nếu phía bên phải không có mặt cho mục tiêu biểu thức thì trình thông dịch sẽ đánh giá mục tiêu ngoại trừ lệnh gọi __setitem__() hoặc __setattr__() cuối cùng.

Xem thêm

PEP 526 - Cú pháp cho chú thích biến

Đề xuất đã thêm cú pháp chú thích các loại biến (bao gồm biến lớp và biến thể hiện), thay vì thể hiện chúng thông qua nhận xét.

PEP 484 - Gợi ý gõ

Đề xuất đã thêm mô-đun typing để cung cấp cú pháp tiêu chuẩn cho các chú thích loại có thể được sử dụng trong các công cụ phân tích tĩnh và IDE.

Thay đổi trong phiên bản 3.8: Giờ đây, các bài tập có chú thích cho phép các biểu thức tương tự ở phía bên phải như các bài tập thông thường. Trước đây, một số biểu thức (như biểu thức bộ dữ liệu không có dấu ngoặc đơn) đã gây ra lỗi cú pháp.

Thay đổi trong phiên bản 3.14: Các chú thích hiện được đánh giá một cách lười biếng trong một annotation scope riêng biệt. Nếu mục tiêu gán không đơn giản thì các chú thích sẽ không bao giờ được đánh giá.

7.3. Tuyên bố assert

Câu lệnh khẳng định là một cách thuận tiện để chèn các xác nhận gỡ lỗi vào chương trình:

assert_stmt: "assert" expression ["," expression]

Dạng đơn giản, assert expression, tương đương với

nếu __gỡ lỗi__:
    nếu không phải  biểu thức: raise AssertionError

Dạng mở rộng, assert expression1, expression2, tương đương với

nếu __gỡ lỗi__:
    nếu không phải biểu thức1: raise AssertionError(express2)

Những sự tương đương này giả định rằng __debug__AssertionError đề cập đến các biến tích hợp có các tên đó. Trong triển khai hiện tại, biến tích hợp __debug__True trong các trường hợp bình thường, False khi yêu cầu tối ưu hóa (tùy chọn dòng lệnh -O). Trình tạo mã hiện tại không phát ra mã cho câu lệnh assert khi yêu cầu tối ưu hóa tại thời điểm biên dịch. Lưu ý rằng không cần thiết phải đưa mã nguồn của biểu thức bị lỗi vào thông báo lỗi; nó sẽ được hiển thị như một phần của dấu vết ngăn xếp.

Việc gán cho __debug__ là bất hợp pháp. Giá trị của biến tích hợp được xác định khi trình thông dịch khởi động.

7.4. Tuyên bố pass

pass_stmt: "pass"

pass là một thao tác rỗng --- khi nó được thực thi, không có gì xảy ra. Nó hữu ích như một trình giữ chỗ khi một câu lệnh được yêu cầu về mặt cú pháp nhưng không cần thực thi mã, ví dụ:

def f(arg): truyền hàm # a mà chưa làm gì cả

lớp C: vượt qua lớp # a mà không có phương thức nào (chưa)

7.5. Tuyên bố del

del_stmt: "del" target_list

Việc xóa được xác định đệ quy rất giống với cách xác định phép gán. Thay vì đánh vần nó một cách chi tiết đầy đủ, đây là một số gợi ý.

Xóa danh sách mục tiêu sẽ xóa đệ quy từng mục tiêu, từ trái sang phải.

Việc xóa tên sẽ loại bỏ ràng buộc của tên đó khỏi không gian tên cục bộ hoặc chung, tùy thuộc vào việc tên đó có xuất hiện trong câu lệnh global trong cùng một khối mã hay không. Cố gắng xóa tên không liên kết sẽ gây ra ngoại lệ NameError.

Việc xóa các tham chiếu thuộc tính và đăng ký được chuyển đến đối tượng chính có liên quan; việc xóa một phần cắt nói chung tương đương với việc gán một lát trống đúng loại (nhưng ngay cả điều này cũng được xác định bởi đối tượng được cắt).

Thay đổi trong phiên bản 3.2: Trước đây, việc xóa tên khỏi không gian tên cục bộ là bất hợp pháp nếu nó xuất hiện dưới dạng biến tự do trong một khối lồng nhau.

7.6. Tuyên bố return

return_stmt: "return" [expression_list]

return chỉ có thể xuất hiện được lồng theo cú pháp trong định nghĩa hàm chứ không phải trong định nghĩa lớp lồng nhau.

Nếu có danh sách biểu thức, nó sẽ được đánh giá, nếu không thì None sẽ được thay thế.

return để lại lệnh gọi hàm hiện tại với danh sách biểu thức (hoặc None) làm giá trị trả về.

Khi return chuyển quyền điều khiển ra khỏi câu lệnh try bằng mệnh đề finally, mệnh đề finally đó sẽ được thực thi trước khi thực sự rời khỏi hàm.

Trong hàm tạo, câu lệnh return cho biết rằng trình tạo đã hoàn tất và sẽ khiến StopIteration được nâng lên. Giá trị trả về (nếu có) được sử dụng làm đối số để xây dựng StopIteration và trở thành thuộc tính StopIteration.value.

Trong hàm tạo không đồng bộ, câu lệnh return trống cho biết rằng trình tạo không đồng bộ đã hoàn tất và sẽ khiến StopAsyncIteration được nâng lên. Câu lệnh return không trống là lỗi cú pháp trong hàm tạo không đồng bộ.

7.7. Tuyên bố yield

yield_stmt: yield_expression

Câu lệnh yield có ngữ nghĩa tương đương với yield expression. Câu lệnh yield có thể được sử dụng để bỏ qua các dấu ngoặc đơn cần có trong câu lệnh biểu thức lợi nhuận tương đương. Ví dụ: các báo cáo lợi nhuận

năng suất <expr>
mang lại từ <expr>

tương đương với các câu lệnh biểu thức lợi suất

(sản lượng <expr>)
(sản lượng từ <expr>)

Các biểu thức và câu lệnh lợi nhuận chỉ được sử dụng khi xác định hàm generator và chỉ được sử dụng trong phần thân của hàm tạo. Việc sử dụng yield trong định nghĩa hàm là đủ để khiến định nghĩa đó tạo ra hàm tạo thay vì hàm thông thường.

Để biết chi tiết đầy đủ về ngữ nghĩa của yield, hãy tham khảo phần biểu thức năng suất.

7.8. Tuyên bố raise

raise_stmt: "raise" [expression ["from" expression]]

Nếu không có biểu thức nào, raise sẽ đưa ra lại ngoại lệ hiện đang được xử lý, còn được gọi là active exception. Nếu hiện tại không có ngoại lệ nào đang hoạt động thì ngoại lệ RuntimeError sẽ xuất hiện cho biết đây là lỗi.

Mặt khác, raise đánh giá biểu thức đầu tiên là đối tượng ngoại lệ. Nó phải là một lớp con hoặc một phiên bản của BaseException. Nếu là một lớp, thể hiện ngoại lệ sẽ được lấy khi cần bằng cách khởi tạo lớp không có đối số.

type của ngoại lệ là lớp của phiên bản ngoại lệ, value chính là phiên bản đó.

Đối tượng truy nguyên thường được tạo tự động khi một ngoại lệ được nêu ra và gắn vào nó dưới dạng thuộc tính __traceback__. Bạn có thể tạo một ngoại lệ và thiết lập truy nguyên của riêng mình trong một bước bằng cách sử dụng phương thức ngoại lệ with_traceback() (trả về cùng một phiên bản ngoại lệ, với truy nguyên được đặt thành đối số của nó), như vậy:

tăng ngoại lệ ("foo đã xảy ra"). with_traceback(tracebackobj)

Mệnh đề from được sử dụng để xâu chuỗi ngoại lệ: nếu được đưa ra, expression thứ hai phải là một lớp hoặc phiên bản ngoại lệ khác. Nếu biểu thức thứ hai là một phiên bản ngoại lệ, nó sẽ được gắn vào ngoại lệ được nêu ra dưới dạng thuộc tính __cause__ (có thể ghi). Nếu biểu thức là một lớp ngoại lệ, lớp đó sẽ được khởi tạo và phiên bản ngoại lệ thu được sẽ được gắn vào ngoại lệ được nêu ra dưới dạng thuộc tính __cause__. Nếu ngoại lệ nêu ra không được xử lý, cả hai ngoại lệ sẽ được in:

>>> thử:
... in(1 / 0)
... ngoại trừ Ngoại lệ  exec:
... raise RuntimeError("Đã xảy ra lỗi gì đó") từ exec
...
Traceback (cuộc gọi gần đây nhất):
  Tệp "<stdin>", dòng 2, trong <module>
    in(1 / 0)
          ~~^~~
ZeroDivisionError: chia cho 0

Ngoại lệ trên là nguyên nhân trực tiếp của ngoại lệ sau:

Traceback (cuộc gọi gần đây nhất):
  Tệp "<stdin>", dòng 4, trong <module>
    raise RuntimeError("Đã xảy ra lỗi gì đó") từ exec
RuntimeError: Đã xảy ra sự cố

Một cơ chế tương tự hoạt động ngầm nếu một ngoại lệ mới được đưa ra khi một ngoại lệ đã được xử lý. Một ngoại lệ có thể được xử lý khi sử dụng mệnh đề except hoặc finally hoặc câu lệnh with. Ngoại lệ trước đó sau đó được đính kèm dưới dạng thuộc tính __context__ của ngoại lệ mới:

>>> thử:
... in(1 / 0)
... ngoại trừ:
... raise RuntimeError("Đã xảy ra lỗi gì đó")
...
Traceback (cuộc gọi gần đây nhất):
  Tệp "<stdin>", dòng 2, trong <module>
    in(1 / 0)
          ~~^~~
ZeroDivisionError: chia cho 0

Trong quá trình xử lý ngoại lệ trên, một ngoại lệ khác đã xảy ra:

Traceback (cuộc gọi gần đây nhất):
  Tệp "<stdin>", dòng 4, trong <module>
    raise RuntimeError("Đã xảy ra lỗi gì đó")
RuntimeError: Đã xảy ra sự cố

Chuỗi ngoại lệ có thể được loại bỏ rõ ràng bằng cách chỉ định None trong mệnh đề from:

>>> thử:
... in(1 / 0)
... ngoại trừ:
... raise RuntimeError("Đã xảy ra lỗi gì đó") từ Không 
...
Traceback (cuộc gọi gần đây nhất):
  Tệp "<stdin>", dòng 4, trong <module>
RuntimeError: Đã xảy ra sự cố

Thông tin bổ sung về các ngoại lệ có thể được tìm thấy trong phần Ngoại lệ và thông tin về cách xử lý các ngoại lệ có trong phần Tuyên bố try.

Thay đổi trong phiên bản 3.3: None hiện được phép là Y trong raise X from Y.

Đã thêm thuộc tính __suppress_context__ để ngăn chặn tự động hiển thị bối cảnh ngoại lệ.

Thay đổi trong phiên bản 3.11: Nếu truy nguyên của ngoại lệ đang hoạt động được sửa đổi trong mệnh đề except, câu lệnh raise tiếp theo sẽ đưa ra ngoại lệ với truy nguyên đã sửa đổi. Trước đây, ngoại lệ đã được đưa ra lại với dấu vết khi nó bị bắt.

7.9. Tuyên bố break

break_stmt: "break"

break chỉ có thể xảy ra được lồng về mặt cú pháp trong vòng lặp for hoặc while, nhưng không được lồng trong định nghĩa hàm hoặc lớp trong vòng lặp đó.

Nó chấm dứt vòng lặp kèm theo gần nhất, bỏ qua mệnh đề else tùy chọn nếu vòng lặp có.

Nếu vòng lặp for bị kết thúc bởi break, mục tiêu điều khiển vòng lặp sẽ giữ nguyên giá trị hiện tại của nó.

Khi break chuyển quyền điều khiển ra khỏi câu lệnh try bằng mệnh đề finally, mệnh đề finally đó sẽ được thực thi trước khi thực sự rời khỏi vòng lặp.

7.10. Tuyên bố continue

continue_stmt: "continue"

continue chỉ có thể xảy ra được lồng về mặt cú pháp trong vòng lặp for hoặc while, nhưng không được lồng trong định nghĩa hàm hoặc lớp trong vòng lặp đó. Nó tiếp tục với chu kỳ tiếp theo của vòng lặp gần nhất.

Khi continue chuyển quyền điều khiển ra khỏi câu lệnh try bằng mệnh đề finally, mệnh đề finally đó sẽ được thực thi trước khi thực sự bắt đầu chu kỳ vòng lặp tiếp theo.

7.11. Tuyên bố import

import_stmt:     "import" module ["as" identifier] ("," module ["as" identifier])*
                 | "from" relative_module "import" identifier ["as" identifier]
                 ("," identifier ["as" identifier])*
                 | "from" relative_module "import" "(" identifier ["as" identifier]
                 ("," identifier ["as" identifier])* [","] ")"
                 | "from" relative_module "import" "*"
module:          (identifier ".")* identifier
relative_module: "."* module | "."+

Câu lệnh nhập cơ bản (không có mệnh đề from) được thực thi theo hai bước:

  1. tìm một mô-đun, tải và khởi tạo nó nếu cần

  2. xác định một hoặc nhiều tên trong không gian tên cục bộ cho phạm vi xảy ra câu lệnh import.

Khi câu lệnh chứa nhiều mệnh đề (được phân tách bằng dấu phẩy), hai bước được thực hiện riêng biệt cho từng mệnh đề, giống như các mệnh đề đã được tách thành các câu lệnh nhập riêng lẻ.

Chi tiết về bước đầu tiên, tìm và tải mô-đun, được mô tả chi tiết hơn trong phần trên import system, phần này cũng mô tả các loại gói và mô-đun khác nhau có thể được nhập, cũng như tất cả các hook có thể được sử dụng để tùy chỉnh hệ thống nhập. Lưu ý rằng lỗi ở bước này có thể cho biết không thể định vị được mô-đun, or rằng đã xảy ra lỗi khi khởi tạo mô-đun, lỗi này bao gồm cả việc thực thi mã của mô-đun.

Nếu mô-đun được yêu cầu được truy xuất thành công, nó sẽ được cung cấp trong không gian tên cục bộ theo một trong ba cách:

  • Nếu tên mô-đun được theo sau bởi as thì tên theo sau as sẽ được liên kết trực tiếp với mô-đun đã nhập.

  • Nếu không có tên nào khác được chỉ định và mô-đun đang được nhập là mô-đun cấp cao nhất thì tên của mô-đun sẽ bị ràng buộc trong không gian tên cục bộ dưới dạng tham chiếu đến mô-đun đã nhập

  • Nếu mô-đun đang được nhập là not là mô-đun cấp cao nhất thì tên của gói cấp cao nhất chứa mô-đun đó sẽ bị ràng buộc trong không gian tên cục bộ dưới dạng tham chiếu đến gói cấp cao nhất. Mô-đun đã nhập phải được truy cập bằng tên đủ điều kiện thay vì truy cập trực tiếp

Biểu mẫu from sử dụng quy trình phức tạp hơn một chút:

  1. tìm mô-đun được chỉ định trong mệnh đề from, tải và khởi tạo nó nếu cần;

  2. đối với mỗi mã định danh được chỉ định trong mệnh đề import:

    1. kiểm tra xem mô-đun đã nhập có thuộc tính có tên đó không

    2. nếu không, hãy thử nhập mô-đun con có tên đó rồi kiểm tra lại mô-đun đã nhập để tìm thuộc tính đó

    3. nếu không tìm thấy thuộc tính, ImportError sẽ được nâng lên.

    4. mặt khác, tham chiếu đến giá trị đó được lưu trữ trong không gian tên cục bộ, sử dụng tên trong mệnh đề as nếu nó có mặt, nếu không thì sử dụng tên thuộc tính

Ví dụ:

import foo # foo được nhập và ràng buộc cục bộ
nhập foo.bar.baz # foo, foo.bar và foo.bar.baz đã nhập, foo bị ràng buộc cục bộ
nhập foo.bar.baz dưới dạng fbb # foo, foo.bar và foo.bar.baz được nhập, foo.bar.baz bị ràng buộc dưới dạng fbb
từ foo.bar import baz # foo, foo.bar và foo.bar.baz được nhập, foo.bar.baz bị ràng buộc dưới dạng baz
từ foo import attr # foo được nhập và foo.attr bị ràng buộc dưới dạng attr

Nếu danh sách số nhận dạng được thay thế bằng dấu sao ('*'), tất cả tên công khai được xác định trong mô-đun sẽ bị ràng buộc trong không gian tên cục bộ trong phạm vi xảy ra câu lệnh import.

public names được xác định bởi một mô-đun được xác định bằng cách kiểm tra không gian tên của mô-đun để tìm biến có tên __all__; nếu được xác định thì nó phải là một chuỗi các chuỗi là các tên được xác định hoặc nhập bởi mô-đun đó. Tên chứa các ký tự không phải là ASCII phải nằm trong normalization form NFKC; xem Các ký tự không phải ASCII trong tên để biết chi tiết. Những cái tên được đưa ra trong __all__ đều được coi là công khai và bắt buộc phải tồn tại. Nếu __all__ không được xác định, tập hợp tên công khai bao gồm tất cả các tên được tìm thấy trong không gian tên của mô-đun không bắt đầu bằng ký tự gạch dưới ('_'). __all__ phải chứa toàn bộ API công khai. Nó nhằm tránh việc vô tình xuất các mục không phải là một phần của API (chẳng hạn như các mô-đun thư viện đã được nhập và sử dụng trong mô-đun).

Hình thức nhập ký tự đại diện --- from module import * --- chỉ được phép ở cấp mô-đun. Cố gắng sử dụng nó trong các định nghĩa lớp hoặc hàm sẽ gây ra SyntaxError.

Khi chỉ định mô-đun nào cần nhập, bạn không phải chỉ định tên tuyệt đối của mô-đun. Khi một mô-đun hoặc gói được chứa trong một gói khác, có thể thực hiện nhập tương đối trong cùng gói hàng đầu mà không cần phải đề cập đến tên gói. Bằng cách sử dụng các dấu chấm ở đầu trong mô-đun hoặc gói được chỉ định sau from, bạn có thể chỉ định mức độ duyệt qua hệ thống phân cấp gói hiện tại mà không cần chỉ định tên chính xác. Một dấu chấm ở đầu có nghĩa là gói hiện tại nơi tồn tại mô-đun thực hiện quá trình nhập. Hai dấu chấm có nghĩa là tăng một cấp gói. Ba dấu chấm tăng hai cấp độ, v.v. Vì vậy, nếu bạn thực thi from . import mod từ một mô-đun trong gói pkg thì cuối cùng bạn sẽ nhập pkg.mod. Nếu bạn thực thi from ..subpkg2 import mod từ bên trong pkg.subpkg1 thì bạn sẽ nhập pkg.subpkg2.mod. Thông số kỹ thuật cho việc nhập tương đối có trong phần Nhập khẩu tương đối gói.

importlib.import_module() được cung cấp để hỗ trợ các ứng dụng xác định động các mô-đun sẽ được tải.

Tăng một auditing event import với các đối số module, filename, sys.path, sys.meta_path, sys.path_hooks.

7.11.1. Tuyên bố tương lai

Zz000zz là một lệnh cho trình biên dịch rằng một mô-đun cụ thể phải được biên dịch bằng cú pháp hoặc ngữ nghĩa sẽ có sẵn trong một bản phát hành Python được chỉ định trong tương lai nơi tính năng này trở thành tiêu chuẩn.

Tuyên bố trong tương lai nhằm mục đích dễ dàng di chuyển sang các phiên bản Python trong tương lai có những thay đổi không tương thích với ngôn ngữ. Nó cho phép sử dụng các tính năng mới trên cơ sở từng mô-đun trước khi phát hành tính năng này trở thành tiêu chuẩn.

future_stmt: "from" "__future__" "import" feature ["as" identifier]
             ("," feature ["as" identifier])*
             | "from" "__future__" "import" "(" feature ["as" identifier]
             ("," feature ["as" identifier])* [","] ")"
feature:     identifier

Một tuyên bố trong tương lai phải xuất hiện ở gần đầu mô-đun. Các dòng duy nhất có thể xuất hiện trước một câu lệnh trong tương lai là:

  • chuỗi tài liệu mô-đun (nếu có),

  • ý kiến,

  • dòng trống và

  • các tuyên bố khác trong tương lai.

Tính năng duy nhất yêu cầu sử dụng câu lệnh tương lai là annotations (xem PEP 563).

Tất cả các tính năng lịch sử được kích hoạt bởi câu lệnh trong tương lai vẫn được Python 3 công nhận. Danh sách này bao gồm absolute_import, division, generators, generator_stop, unicode_literals, print_function, nested_scopeswith_statement. Tất cả chúng đều dư thừa vì chúng luôn được bật và chỉ được giữ lại để tương thích ngược.

Một tuyên bố trong tương lai được nhận dạng và xử lý đặc biệt tại thời điểm biên dịch: Những thay đổi về ngữ nghĩa của các cấu trúc cốt lõi thường được triển khai bằng cách tạo ra các mã khác nhau. Thậm chí có thể xảy ra trường hợp một tính năng mới đưa ra cú pháp mới không tương thích (chẳng hạn như một từ dành riêng mới), trong trường hợp đó trình biên dịch có thể cần phân tích mô-đun theo cách khác. Những quyết định như vậy không thể bị trì hoãn cho đến khi chạy.

Đối với bất kỳ bản phát hành cụ thể nào, trình biên dịch sẽ biết tên tính năng nào đã được xác định và đưa ra lỗi thời gian biên dịch nếu một câu lệnh trong tương lai chứa một tính năng mà nó không biết.

Ngữ nghĩa thời gian chạy trực tiếp giống như đối với bất kỳ câu lệnh nhập nào: có một mô-đun tiêu chuẩn __future__, được mô tả sau và nó sẽ được nhập theo cách thông thường tại thời điểm câu lệnh tương lai được thực thi.

Ngữ nghĩa thời gian chạy thú vị phụ thuộc vào tính năng cụ thể được kích hoạt bởi câu lệnh tương lai.

Lưu ý rằng không có gì đặc biệt về câu lệnh:

nhập __future__ [dưới tên]

Đó không phải là một tuyên bố trong tương lai; đó là một câu lệnh nhập thông thường không có hạn chế về cú pháp hoặc ngữ nghĩa đặc biệt.

Mã được biên dịch bằng lệnh gọi đến các hàm dựng sẵn exec()compile() xuất hiện trong mô-đun M chứa câu lệnh tương lai, theo mặc định, sẽ sử dụng cú pháp hoặc ngữ nghĩa mới được liên kết với câu lệnh tương lai. Điều này có thể được kiểm soát bằng các đối số tùy chọn cho compile() --- xem tài liệu về hàm đó để biết chi tiết.

Câu lệnh trong tương lai được nhập tại dấu nhắc của trình thông dịch tương tác sẽ có hiệu lực trong phần còn lại của phiên thông dịch. Nếu trình thông dịch được khởi động bằng tùy chọn -i, được chuyển tên tập lệnh để thực thi và tập lệnh bao gồm câu lệnh trong tương lai, thì tập lệnh đó sẽ có hiệu lực trong phiên tương tác bắt đầu sau khi tập lệnh được thực thi.

Xem thêm

PEP 236 - Trở về __tương lai__

Đề xuất ban đầu cho cơ chế __future__.

7.12. Tuyên bố global

global_stmt: "global" identifier ("," identifier)*

Câu lệnh global khiến các mã định danh được liệt kê được hiểu là toàn cục. Sẽ không thể gán cho một biến toàn cục mà không có global, mặc dù các biến tự do có thể tham chiếu đến các biến toàn cục mà không được khai báo toàn cục.

Câu lệnh global áp dụng cho toàn bộ phạm vi hiện tại (mô-đun, nội dung hàm hoặc định nghĩa lớp). Một SyntaxError được nâng lên nếu một biến được sử dụng hoặc được gán trước khi khai báo toàn cục trong phạm vi.

Ở cấp độ mô-đun, tất cả các biến đều mang tính toàn cục, do đó câu lệnh global không có hiệu lực. Tuy nhiên, các biến vẫn không được sử dụng hoặc gán trước khi khai báo global. Yêu cầu này được nới lỏng trong lời nhắc tương tác (REPL).

Programmer's note: global là một lệnh cho trình phân tích cú pháp. Nó chỉ áp dụng cho mã được phân tích cú pháp cùng lúc với câu lệnh global. Cụ thể, câu lệnh global chứa trong một chuỗi hoặc đối tượng mã được cung cấp cho hàm exec() tích hợp không ảnh hưởng đến khối mã containing lệnh gọi hàm và mã chứa trong chuỗi như vậy không bị ảnh hưởng bởi các câu lệnh global trong mã chứa lệnh gọi hàm. Điều tương tự cũng áp dụng cho các hàm eval()compile().

7.13. Tuyên bố nonlocal

nonlocal_stmt: "nonlocal" identifier ("," identifier)*

Khi định nghĩa của một hàm hoặc lớp được lồng (đính kèm) bên trong các định nghĩa của các hàm khác, phạm vi không cục bộ của nó là phạm vi cục bộ của các hàm kèm theo. Câu lệnh nonlocal khiến các mã định danh được liệt kê tham chiếu đến các tên bị ràng buộc trước đó trong phạm vi không cục bộ. Nó cho phép mã được đóng gói để liên kết lại các mã định danh không cục bộ như vậy. Nếu một tên bị ràng buộc trong nhiều phạm vi không tiêu điểm, thì ràng buộc gần nhất sẽ được sử dụng. Nếu một tên không bị ràng buộc trong bất kỳ phạm vi không cục bộ nào hoặc nếu không có phạm vi không cục bộ thì SyntaxError sẽ được nâng lên.

Câu lệnh nonlocal áp dụng cho toàn bộ phạm vi của hàm hoặc nội dung lớp. Một SyntaxError được nâng lên nếu một biến được sử dụng hoặc được gán trước khai báo không tiêu điểm của nó trong phạm vi.

Xem thêm

PEP 3104 - Truy cập vào tên trong phạm vi bên ngoài

Thông số kỹ thuật cho câu lệnh nonlocal.

Programmer's note: nonlocal là một lệnh cho trình phân tích cú pháp và chỉ áp dụng cho mã được phân tích cú pháp cùng với nó. Xem ghi chú cho câu lệnh global.

7.14. Tuyên bố type

type_stmt: 'type' identifier [type_params] "=" expression

Câu lệnh type khai báo một bí danh loại, là một thể hiện của typing.TypeAliasType.

Ví dụ: câu lệnh sau tạo bí danh loại:

 Điểm = tuple[float, float]

Mã này gần tương đương với:

chú thích-def VALUE_OF_Point():
    trả về tuple[float, float]
Điểm = .TypeAliasType("Điểm", VALUE_OF_Point())

annotation-def biểu thị annotation scope, hoạt động gần giống như một hàm, nhưng có một số khác biệt nhỏ.

Giá trị của bí danh loại được đánh giá trong phạm vi chú thích. Nó không được đánh giá khi bí danh loại được tạo mà chỉ khi giá trị được truy cập thông qua thuộc tính __value__ của bí danh loại (xem Đánh giá lười biếng). Điều này cho phép bí danh loại tham chiếu đến các tên chưa được xác định.

Bí danh loại có thể được đặt chung bằng cách thêm type parameter list sau tên. Xem Bí danh loại chung để biết thêm.

typesoft keyword.

Added in version 3.12.

Xem thêm

PEP 695 - Cú pháp tham số loại

Giới thiệu câu lệnh và cú pháp type cho các lớp và hàm chung.