6. Biểu thức

Chương này giải thích ý nghĩa của các thành phần biểu thức trong Python.

Syntax Notes: Trong chương này và các chương tiếp theo, grammar notation sẽ được sử dụng để mô tả cú pháp chứ không phải phân tích từ vựng.

Khi (một lựa chọn thay thế) một quy tắc cú pháp có dạng:

name: othername

và không có ngữ nghĩa nào được đưa ra, ngữ nghĩa của dạng name này giống như đối với othername.

6.1. chuyển đổi số học

Khi mô tả toán tử số học bên dưới sử dụng cụm từ "các đối số số được chuyển đổi thành kiểu thực phổ biến", điều này có nghĩa là việc triển khai toán tử cho các kiểu số tích hợp hoạt động như được mô tả trong phần Numeric Types của tài liệu thư viện tiêu chuẩn.

Một số quy tắc bổ sung áp dụng cho một số toán tử và toán hạng không phải số nhất định (ví dụ: một chuỗi làm đối số bên trái cho toán tử %). Tiện ích mở rộng phải xác định hành vi chuyển đổi của riêng chúng.

6.2. nguyên tử

Nguyên tử là thành phần cơ bản nhất của biểu thức. Các nguyên tử đơn giản nhất là names hoặc chữ. Các dạng được đặt trong dấu ngoặc đơn, dấu ngoặc hoặc dấu ngoặc nhọn cũng được phân loại về mặt cú pháp là nguyên tử.

Chính thức, cú pháp cho các nguyên tử là:

atom:
   | 'True'
   | 'False'
   | 'None'
   | '...'
   | identifier
   | literal
   | enclosure
enclosure:
   | parenth_form
   | list_display
   | dict_display
   | set_display
   | generator_expression
   | yield_atom

6.2.1. Các hằng số tích hợp

Các từ khóa True, FalseNone có tên built-in constants. Mã thông báo ... đặt tên cho hằng số Ellipsis.

Đánh giá các nguyên tử này mang lại giá trị tương ứng.

Ghi chú

Một số hằng số tích hợp khác có sẵn dưới dạng biến toàn cục, nhưng chỉ những hằng số được đề cập ở đây là keywords. Đặc biệt, những tên này không thể được gán lại hoặc sử dụng làm thuộc tính:

>>> Sai = 123
  Tệp "<input>", dòng 1
   Sai = 123
   ^^ ^^^
Lỗi cú pháp: không thể gán cho Sai

6.2.2. Mã định danh (Tên)

Một mã định danh xuất hiện dưới dạng một nguyên tử là một cái tên. Xem phần Tên (số nhận dạng và từ khóa) để biết định nghĩa từ vựng và phần Đặt tên và ràng buộc để biết tài liệu về cách đặt tên và ràng buộc.

Khi tên được gắn với một đối tượng, việc đánh giá nguyên tử sẽ mang lại đối tượng đó. Khi một tên không bị ràng buộc, nỗ lực đánh giá tên đó sẽ tạo ra ngoại lệ NameError.

6.2.2.1. Xáo trộn tên riêng

Khi một mã định danh xuất hiện ở dạng văn bản trong định nghĩa lớp bắt đầu bằng hai hoặc nhiều ký tự gạch dưới và không kết thúc bằng hai hoặc nhiều dấu gạch dưới, nó được coi là private name của lớp đó.

Xem thêm

Z000zz.

Chính xác hơn, tên riêng được chuyển đổi sang dạng dài hơn trước khi mã được tạo cho chúng. Nếu tên được chuyển đổi dài hơn 255 ký tự, việc cắt ngắn do triển khai xác định có thể xảy ra.

Việc chuyển đổi độc lập với ngữ cảnh cú pháp trong đó mã định danh được sử dụng nhưng chỉ các mã định danh riêng sau đây được đọc sai:

  • Bất kỳ tên nào được sử dụng làm tên của biến được gán hoặc đọc hoặc bất kỳ tên nào của thuộc tính đang được truy cập.

    Tuy nhiên, thuộc tính __name__ của các hàm, lớp và bí danh kiểu lồng nhau không bị sai.

  • Tên của các mô-đun đã nhập, ví dụ: __spam trong import __spam. Nếu mô-đun là một phần của gói (tức là tên của nó có chứa dấu chấm), thì tên đó là not bị đọc sai, ví dụ: __foo trong import __foo.bar không bị đọc sai.

  • Tên của thành viên được nhập, ví dụ: __f trong from spam import __f.

Quy tắc chuyển đổi được xác định như sau:

  • Tên lớp, với các dấu gạch dưới ở đầu đã được loại bỏ và một dấu gạch dưới ở đầu được chèn vào, được chèn vào phía trước mã định danh, ví dụ: mã định danh __spam xuất hiện trong một lớp có tên Foo, _Foo hoặc __Foo được chuyển đổi thành _Foo__spam.

  • Nếu tên lớp chỉ bao gồm dấu gạch dưới, thì phép biến đổi là danh tính, ví dụ: mã định danh __spam xuất hiện trong lớp có tên _ hoặc __ được giữ nguyên.

6.2.3. chữ

Zz000zz là biểu diễn văn bản của một giá trị. Python hỗ trợ các ký tự số, chuỗi và byte. Format stringstemplate strings được coi là chuỗi ký tự.

Các chữ số bao gồm một mã thông báo NUMBER duy nhất, đặt tên cho một số nguyên, số dấu phẩy động hoặc số ảo. Xem phần Chữ số trong tài liệu phân tích từ vựng để biết chi tiết.

Chuỗi và byte bằng chữ có thể bao gồm một số mã thông báo. Xem phần Nối chuỗi theo nghĩa đen để biết chi tiết.

Lưu ý rằng các số âm và số phức, như -3 hoặc 3+4.2j, về mặt cú pháp không phải là chữ cái mà là các phép toán số học unary hoặc binary liên quan đến toán tử - hoặc +.

Việc đánh giá một nghĩa đen mang lại một đối tượng thuộc loại nhất định (int, float, complex, str, bytes hoặc Template) với giá trị đã cho. Giá trị có thể gần đúng trong trường hợp dấu phẩy động và chữ ảo.

Ngữ pháp chính thức cho nghĩa đen là:

literal: strings | NUMBER

6.2.3.1. Chữ và nhận dạng đối tượng

Tất cả các chữ tương ứng với các kiểu dữ liệu bất biến và do đó danh tính của đối tượng ít quan trọng hơn giá trị của nó. Nhiều đánh giá về các chữ có cùng giá trị (cùng một lần xuất hiện trong văn bản chương trình hoặc một lần xuất hiện khác) có thể thu được cùng một đối tượng hoặc một đối tượng khác có cùng giá trị.

Chi tiết triển khai CPython

Ví dụ: trong CPython, các số nguyên small có cùng giá trị sẽ đánh giá cho cùng một đối tượng

>>> x = 7
>>> y = 7
>>> x  y
đúng

Tuy nhiên, số nguyên lớn đánh giá các đối tượng khác nhau:

>>> x = 123456789
>>> y = 123456789
>>> x  y
sai

Hành vi này có thể thay đổi trong các phiên bản CPython trong tương lai. Đặc biệt, ranh giới giữa số nguyên "nhỏ" và số nguyên "lớn" đã thay đổi trong quá khứ.

CPython sẽ phát ra SyntaxWarning khi bạn so sánh các chữ bằng cách sử dụng is:

>>> x = 7
>>> x  7
<input>:1: Cú phápCảnh báo: "là" với chữ 'int'. Ý bạn là "=="?
đúng

Xem Khi nào tôi có thể dựa vào các bài kiểm tra danh tính bằng toán tử is? để biết thêm thông tin.

Template strings là bất biến nhưng có thể tham chiếu các đối tượng có thể thay đổi dưới dạng giá trị Interpolation. Vì mục đích của phần này, hai chuỗi t có "giá trị giống nhau" nếu cả cấu trúc của chúng và identity của các giá trị đều khớp nhau.

Hiện tại, mỗi lần đánh giá một chuỗi mẫu đều dẫn đến một đối tượng khác nhau.

6.2.3.2. Nối chuỗi theo nghĩa đen

Cho phép nhiều chuỗi ký tự hoặc byte liền kề, có thể sử dụng các quy ước trích dẫn khác nhau, và ý nghĩa của chúng giống như cách nối của chúng:

>>> "xin chào" 'thế giới'
"xin chào thế giới"

Tính năng này được xác định ở cấp độ cú pháp, vì vậy nó chỉ hoạt động với chữ. Để nối các biểu thức chuỗi trong thời gian chạy, toán tử '+' có thể được sử dụng

>>> lời chào = "Xin chào"
>>> khoảng trắng = " "
>>> tên = "Blaise"
>>> print(chào + dấu cách + tên) # not: print(tên dấu cách chào)
Xin chào Blaise

Ghép nối theo nghĩa đen có thể tự do trộn các chuỗi thô, chuỗi trích dẫn ba và chuỗi ký tự được định dạng. Ví dụ:

>>> "Xin chào" r', ' f"{name}!"
"Xin chào, Blaise!"

Tính năng này có thể được sử dụng để giảm số lượng dấu gạch chéo ngược cần thiết, để phân chia các chuỗi dài một cách thuận tiện trên các dòng dài hoặc thậm chí để thêm nhận xét vào các phần của chuỗi. Ví dụ:

re.compile("[A-Za-z_]" # letter hoặc gạch dưới
           "[A-Za-z0-9_]*" # letter, chữ số hoặc dấu gạch dưới
          )

Tuy nhiên, các ký tự byte chỉ có thể được kết hợp với các ký tự byte khác; không phải với bất kỳ loại chuỗi ký tự nào. Ngoài ra, các ký tự chuỗi mẫu chỉ có thể được kết hợp với các ký tự chuỗi mẫu khác

>>> t"Xin chào" t"{name}!"
Bản mẫu(strings=('Xin chào', '!'), nội suy=(...))

Chính thức:

strings: (STRING | fstring)+ | tstring+

6.2.4. Biểu mẫu trong ngoặc đơn

Biểu mẫu được đặt trong ngoặc đơn là danh sách biểu thức tùy chọn được đặt trong dấu ngoặc đơn:

parenth_form: "(" [starred_expression] ")"

Danh sách biểu thức trong ngoặc đơn sẽ mang lại bất kỳ kết quả nào mà danh sách biểu thức đó mang lại: nếu danh sách chứa ít nhất một dấu phẩy thì nó sẽ tạo ra một bộ dữ liệu; mặt khác, nó mang lại biểu thức duy nhất tạo nên danh sách biểu thức.

Một cặp dấu ngoặc đơn trống sẽ tạo ra một đối tượng bộ dữ liệu trống. Vì các bộ dữ liệu là bất biến nên các quy tắc tương tự như đối với các hằng được áp dụng (tức là, hai lần xuất hiện của bộ dữ liệu trống có thể mang lại hoặc không thể tạo ra cùng một đối tượng).

Lưu ý rằng các bộ dữ liệu không được hình thành bằng dấu ngoặc đơn mà bằng cách sử dụng dấu phẩy. Ngoại lệ là bộ dữ liệu trống, cần có dấu ngoặc đơn are --- việc cho phép "không có gì" không được ghi trong ngoặc đơn trong các biểu thức sẽ gây ra sự mơ hồ và cho phép các lỗi chính tả phổ biến được bỏ qua.

6.2.5. Hiển thị danh sách, bộ và từ điển

Để xây dựng một danh sách, một tập hợp hoặc một từ điển Python cung cấp cú pháp đặc biệt gọi là "hiển thị", mỗi cú pháp có hai loại:

  • nội dung vùng chứa được liệt kê rõ ràng hoặc

  • chúng được tính toán thông qua một tập hợp các hướng dẫn lặp và lọc, được gọi là comprehension.

Các yếu tố cú pháp phổ biến để hiểu là:

comprehension: assignment_expression comp_for
comp_for:      ["async"] "for" target_list "in" or_test [comp_iter]
comp_iter:     comp_for | comp_if
comp_if:       "if" or_test [comp_iter]

Việc hiểu bao gồm một biểu thức duy nhất theo sau là ít nhất một mệnh đề for và không hoặc nhiều mệnh đề for hoặc if. Trong trường hợp này, các phần tử của vùng chứa mới là những phần tử sẽ được tạo ra bằng cách coi mỗi mệnh đề for hoặc if là một khối, lồng từ trái sang phải và đánh giá biểu thức để tạo ra một phần tử mỗi khi đạt đến khối trong cùng.

Tuy nhiên, ngoài biểu thức có thể lặp lại trong mệnh đề for ngoài cùng bên trái, việc hiểu được thực hiện trong một phạm vi lồng nhau ngầm riêng biệt. Điều này đảm bảo rằng các tên được gán trong danh sách mục tiêu không "rò rỉ" vào phạm vi kèm theo.

Biểu thức có thể lặp lại trong mệnh đề for ngoài cùng bên trái được đánh giá trực tiếp trong phạm vi kèm theo và sau đó được chuyển dưới dạng đối số cho phạm vi được lồng ngầm. Các mệnh đề for tiếp theo và bất kỳ điều kiện lọc nào trong mệnh đề for ngoài cùng bên trái đều không thể được đánh giá trong phạm vi kèm theo vì chúng có thể phụ thuộc vào các giá trị thu được từ lần lặp ngoài cùng bên trái. Ví dụ: [x*y for x in range(10) for y in range(x, x+10)].

Để đảm bảo việc hiểu luôn dẫn đến vùng chứa thuộc loại thích hợp, các biểu thức yieldyield from bị cấm trong phạm vi được lồng ngầm.

Kể từ Python 3.6, trong hàm async def, mệnh đề async for có thể được sử dụng để lặp lại asynchronous iterator. Phần hiểu trong hàm async def có thể bao gồm mệnh đề for hoặc async for theo sau biểu thức dẫn đầu, có thể chứa các mệnh đề for hoặc async for bổ sung và cũng có thể sử dụng các biểu thức await.

Nếu một cách hiểu chứa các mệnh đề async for hoặc nếu nó chứa các biểu thức await hoặc các cách hiểu không đồng bộ khác ở bất kỳ đâu ngoại trừ biểu thức có thể lặp lại trong mệnh đề for ngoài cùng bên trái thì nó được gọi là asynchronous comprehension. Việc hiểu không đồng bộ có thể tạm dừng việc thực thi hàm coroutine mà nó xuất hiện. Xem thêm PEP 530.

Added in version 3.6: Sự hiểu biết không đồng bộ đã được giới thiệu.

Thay đổi trong phiên bản 3.8: yieldyield from bị cấm trong phạm vi lồng nhau.

Thay đổi trong phiên bản 3.11: Việc hiểu không đồng bộ hiện được phép hiểu bên trong các hàm không đồng bộ. Sự hiểu biết bên ngoài ngầm trở nên không đồng bộ.

6.2.6. Danh sách hiển thị

Hiển thị danh sách là một chuỗi biểu thức có thể trống được đặt trong dấu ngoặc vuông:

list_display: "[" [flexible_expression_list | comprehension] "]"

Việc hiển thị danh sách mang lại một đối tượng danh sách mới, nội dung được chỉ định bởi danh sách biểu thức hoặc mức độ hiểu. Khi cung cấp danh sách biểu thức được phân tách bằng dấu phẩy, các phần tử của nó sẽ được đánh giá từ trái sang phải và được đặt vào đối tượng danh sách theo thứ tự đó. Khi một sự hiểu biết được cung cấp, danh sách được xây dựng từ các yếu tố có được từ sự hiểu biết.

6.2.7. Đặt hiển thị

Màn hình tập hợp được biểu thị bằng dấu ngoặc nhọn và có thể phân biệt với màn hình từ điển do thiếu dấu hai chấm phân tách các khóa và giá trị:

set_display: "{" (flexible_expression_list | comprehension) "}"

Màn hình tập hợp mang lại một đối tượng tập hợp có thể thay đổi mới, nội dung được chỉ định bởi một chuỗi biểu thức hoặc mức độ hiểu. Khi cung cấp danh sách biểu thức được phân tách bằng dấu phẩy, các phần tử của nó sẽ được đánh giá từ trái sang phải và được thêm vào đối tượng đã đặt. Khi một sự hiểu biết được cung cấp, tập hợp được xây dựng từ các phần tử có được từ sự hiểu biết đó.

Không thể xây dựng một tập hợp trống bằng {}; nghĩa đen này xây dựng một từ điển trống.

6.2.8. Hiển thị từ điển

Màn hình từ điển có thể là một chuỗi các mục chính tả (cặp khóa/giá trị) có thể trống được đặt trong dấu ngoặc nhọn:

dict_display:       "{" [dict_item_list | dict_comprehension] "}"
dict_item_list:     dict_item ("," dict_item)* [","]
dict_item:          expression ":" expression | "**" or_expr
dict_comprehension: expression ":" expression comp_for

Việc hiển thị từ điển mang lại một đối tượng từ điển mới.

Nếu một chuỗi các mục dict được phân tách bằng dấu phẩy, chúng sẽ được đánh giá từ trái sang phải để xác định các mục của từ điển: mỗi đối tượng khóa được sử dụng làm khóa vào từ điển để lưu trữ giá trị tương ứng. Điều này có nghĩa là bạn có thể chỉ định cùng một khóa nhiều lần trong danh sách mục chính tả và giá trị của từ điển cuối cùng cho khóa đó sẽ là giá trị cuối cùng được đưa ra.

Dấu hoa thị kép ** biểu thị dictionary unpacking. Toán hạng của nó phải là mapping. Mỗi mục ánh xạ sẽ được thêm vào từ điển mới. Các giá trị sau này thay thế các giá trị đã được đặt bởi các mục chính tả trước đó và việc giải nén từ điển trước đó.

Added in version 3.5: Giải nén vào màn hình từ điển, ban đầu được đề xuất bởi PEP 448.

Việc hiểu chính tả, trái ngược với việc hiểu danh sách và tập hợp, cần hai biểu thức được phân tách bằng dấu hai chấm, theo sau là các mệnh đề "for" và "if" thông thường. Khi quá trình hiểu được chạy, các phần tử khóa và giá trị thu được sẽ được chèn vào từ điển mới theo thứ tự chúng được tạo ra.

Các hạn chế về loại giá trị khóa được liệt kê trước đó trong phần Hệ thống phân cấp loại tiêu chuẩn. (Tóm lại, loại khóa phải là hashable, loại trừ tất cả các đối tượng có thể thay đổi.) Không phát hiện xung đột giữa các khóa trùng lặp; giá trị cuối cùng (văn bản ngoài cùng bên phải trong màn hình) được lưu trữ cho một giá trị khóa nhất định sẽ chiếm ưu thế.

Thay đổi trong phiên bản 3.8: Trước Python 3.8, trong khả năng hiểu chính tả, thứ tự đánh giá khóa và giá trị không được xác định rõ ràng. Trong CPython, giá trị được đánh giá trước khóa. Bắt đầu với 3.8, khóa được đánh giá trước giá trị, theo đề xuất của PEP 572.

6.2.9. biểu thức trình tạo

Biểu thức trình tạo là ký hiệu trình tạo nhỏ gọn trong ngoặc đơn:

generator_expression: "(" expression comp_for ")"

Một biểu thức trình tạo mang lại một đối tượng trình tạo mới. Cú pháp của nó giống như đối với phần hiểu, ngoại trừ việc nó được đặt trong dấu ngoặc đơn thay vì dấu ngoặc hoặc dấu ngoặc nhọn.

Các biến được sử dụng trong biểu thức trình tạo được đánh giá một cách lười biếng khi phương thức __next__() được gọi cho đối tượng trình tạo (theo cách tương tự như các trình tạo thông thường). Tuy nhiên, biểu thức lặp trong mệnh đề for ngoài cùng bên trái sẽ được đánh giá ngay lập tức và iterator ngay lập tức được tạo cho lần lặp đó, do đó, lỗi tạo ra trong khi tạo trình vòng lặp sẽ được phát ra tại điểm mà biểu thức trình tạo được xác định, thay vì tại điểm truy xuất giá trị đầu tiên. Các mệnh đề for tiếp theo và bất kỳ điều kiện lọc nào trong mệnh đề for ngoài cùng bên trái đều không thể được đánh giá trong phạm vi kèm theo vì chúng có thể phụ thuộc vào các giá trị thu được từ lần lặp ngoài cùng bên trái. Ví dụ: (x*y for x in range(10) for y in range(x, x+10)).

Dấu ngoặc đơn có thể được bỏ qua trong các lệnh gọi chỉ có một đối số. Xem phần Cuộc gọi để biết chi tiết.

Để tránh can thiệp vào hoạt động dự kiến của chính biểu thức trình tạo, các biểu thức yieldyield from bị cấm trong trình tạo được xác định ngầm.

Nếu một biểu thức trình tạo chứa mệnh đề async for hoặc biểu thức await thì nó được gọi là asynchronous generator expression. Biểu thức trình tạo không đồng bộ trả về một đối tượng trình tạo không đồng bộ mới, là một trình vòng lặp không đồng bộ (xem Trình lặp không đồng bộ).

Added in version 3.6: Các biểu thức trình tạo không đồng bộ đã được giới thiệu.

Thay đổi trong phiên bản 3.7: Trước Python 3.7, các biểu thức trình tạo không đồng bộ chỉ có thể xuất hiện trong coroutine async def. Bắt đầu từ phiên bản 3.7, bất kỳ hàm nào cũng có thể sử dụng biểu thức trình tạo không đồng bộ.

Thay đổi trong phiên bản 3.8: yieldyield from bị cấm trong phạm vi lồng nhau.

6.2.10. biểu thức năng suất

yield_atom:       "(" yield_expression ")"
yield_from:       "yield" "from" expression
yield_expression: "yield" yield_list | yield_from

Biểu thức lợi nhuận được sử dụng khi xác định hàm generator hoặc hàm asynchronous generator và do đó chỉ có thể được sử dụng trong phần nội dung của định nghĩa hàm. Việc sử dụng biểu thức lợi nhuận trong phần nội dung của hàm sẽ khiến hàm đó trở thành hàm tạo và việc sử dụng biểu thức đó trong phần nội dung của hàm async def sẽ khiến hàm coroutine đó trở thành hàm tạo không đồng bộ. Ví dụ:

def gen(): # defines một hàm tạo
    năng suất 123

async def agen(): # defines một hàm tạo không đồng bộ
    năng suất 123

Do tác dụng phụ của chúng đối với phạm vi chứa, các biểu thức yield không được phép như một phần của phạm vi được xác định ngầm được sử dụng để triển khai các biểu thức hiểu và trình tạo.

Thay đổi trong phiên bản 3.8: Các biểu thức lợi nhuận bị cấm trong phạm vi lồng nhau ngầm được sử dụng để triển khai các biểu thức hiểu và trình tạo.

Các chức năng của bộ tạo được mô tả bên dưới, trong khi các chức năng của bộ tạo không đồng bộ được mô tả riêng trong phần Chức năng tạo không đồng bộ.

Khi một hàm tạo được gọi, nó sẽ trả về một trình lặp được gọi là trình tạo. Trình tạo đó sau đó sẽ điều khiển việc thực thi chức năng của trình tạo. Việc thực thi bắt đầu khi một trong các phương thức của trình tạo được gọi. Vào thời điểm đó, quá trình thực thi sẽ chuyển sang biểu thức lợi nhuận đầu tiên, tại đó nó sẽ bị tạm dừng một lần nữa, trả về giá trị của yield_list cho người gọi trình tạo hoặc None nếu yield_list bị bỏ qua. Khi bị tạm dừng, chúng tôi muốn nói rằng tất cả trạng thái cục bộ đều được giữ lại, bao gồm các ràng buộc hiện tại của các biến cục bộ, con trỏ lệnh, ngăn xếp đánh giá nội bộ và trạng thái xử lý bất kỳ ngoại lệ nào. Khi quá trình thực thi được tiếp tục bằng cách gọi một trong các phương thức của trình tạo, hàm có thể tiến hành chính xác như thể biểu thức lợi nhuận chỉ là một lệnh gọi bên ngoài khác. Giá trị của biểu thức lợi nhuận sau khi tiếp tục phụ thuộc vào phương thức tiếp tục thực hiện. Nếu __next__() được sử dụng (thường thông qua nội dung for hoặc next()) thì kết quả là None. Mặt khác, nếu send() được sử dụng thì kết quả sẽ là giá trị được truyền vào phương thức đó.

Tất cả những điều này làm cho các hàm tạo khá giống với coroutine; chúng mang lại lợi nhuận nhiều lần, chúng có nhiều điểm vào và việc thực thi chúng có thể bị tạm dừng. Sự khác biệt duy nhất là hàm tạo không thể kiểm soát nơi thực thi sẽ tiếp tục sau khi nó đạt kết quả; quyền điều khiển luôn được chuyển đến người gọi của trình tạo.

Biểu thức lợi nhuận được cho phép ở bất kỳ đâu trong cấu trúc try. Nếu trình tạo không được tiếp tục lại trước khi nó được hoàn thiện (bằng cách đạt đến số tham chiếu bằng 0 hoặc do bị thu gom rác), phương thức close() của trình tạo-iterator sẽ được gọi, cho phép mọi mệnh đề finally đang chờ xử lý thực thi.

Khi sử dụng yield from <expr>, biểu thức được cung cấp phải là biểu thức có thể lặp lại. Các giá trị được tạo ra bằng cách lặp lại iterable đó sẽ được chuyển trực tiếp đến người gọi các phương thức của trình tạo hiện tại. Mọi giá trị được truyền bằng send() và mọi ngoại lệ được truyền bằng throw() đều được chuyển đến trình vòng lặp cơ bản nếu nó có các phương thức thích hợp. Nếu không phải như vậy thì send() sẽ tăng AttributeError hoặc TypeError, trong khi throw() sẽ chỉ tăng ngoại lệ đã vượt qua ngay lập tức.

Khi trình vòng lặp cơ bản hoàn tất, thuộc tính value của phiên bản StopIteration được nâng lên sẽ trở thành giá trị của biểu thức lợi nhuận. Nó có thể được đặt rõ ràng khi tăng StopIteration hoặc tự động khi bộ tạo con là bộ tạo (bằng cách trả về một giá trị từ bộ tạo con).

Thay đổi trong phiên bản 3.3: Đã thêm yield from <expr> để ủy quyền luồng điều khiển cho bộ phụ.

Dấu ngoặc đơn có thể được bỏ qua khi biểu thức lợi nhuận là biểu thức duy nhất ở phía bên phải của câu lệnh gán.

Xem thêm

PEP 255 - Máy phát điện đơn giản

Đề xuất thêm trình tạo và câu lệnh yield vào Python.

PEP 342 - Coroutine thông qua Trình tạo nâng cao

Đề xuất nâng cao API và cú pháp của các trình tạo, giúp chúng có thể sử dụng được dưới dạng các coroutine đơn giản.

PEP 380 - Cú pháp ủy quyền cho một máy phát điện phụ

Đề xuất giới thiệu cú pháp yield_from, giúp việc ủy quyền cho các máy phát điện phụ trở nên dễ dàng.

PEP 525 - Trình tạo không đồng bộ

Đề xuất mở rộng trên PEP 492 bằng cách thêm khả năng tạo vào các hàm coroutine.

6.2.10.1. Phương pháp tạo-lặp

Tiểu mục này mô tả các phương thức của trình lặp trình tạo. Chúng có thể được sử dụng để kiểm soát việc thực hiện chức năng của trình tạo.

Lưu ý rằng việc gọi bất kỳ phương thức tạo nào bên dưới khi trình tạo đang thực thi sẽ gây ra ngoại lệ ValueError.

generator.__next__()

Bắt đầu thực thi hàm tạo hoặc tiếp tục lại ở biểu thức lợi nhuận được thực thi cuối cùng. Khi hàm tạo được tiếp tục bằng phương thức __next__(), biểu thức lợi nhuận hiện tại luôn ước tính là None. Sau đó, quá trình thực thi tiếp tục đến biểu thức lợi nhuận tiếp theo, trong đó trình tạo lại bị treo và giá trị của yield_list được trả về cho người gọi __next__(). Nếu trình tạo thoát mà không mang lại giá trị khác, ngoại lệ StopIteration sẽ xuất hiện.

Phương pháp này thường được gọi ngầm, ví dụ: bằng vòng lặp for hoặc bằng chức năng next() tích hợp.

generator.send(value)

Tiếp tục thực thi và "gửi" một giá trị vào hàm tạo. Đối số value trở thành kết quả của biểu thức lợi nhuận hiện tại. Phương thức send() trả về giá trị tiếp theo do trình tạo mang lại hoặc tăng StopIteration nếu trình tạo thoát mà không mang lại giá trị khác. Khi send() được gọi để khởi động trình tạo, nó phải được gọi với None làm đối số, vì không có biểu thức lợi nhuận nào có thể nhận giá trị.

generator.throw(value)
generator.throw(type[, value[, traceback]])

Đưa ra một ngoại lệ tại thời điểm trình tạo bị tạm dừng và trả về giá trị tiếp theo do hàm tạo mang lại. Nếu trình tạo thoát mà không mang lại giá trị khác, ngoại lệ StopIteration sẽ xuất hiện. Nếu hàm tạo không bắt được ngoại lệ được truyền vào hoặc đưa ra một ngoại lệ khác thì ngoại lệ đó sẽ truyền tới người gọi.

Trong cách sử dụng thông thường, điều này được gọi với một trường hợp ngoại lệ duy nhất tương tự như cách sử dụng từ khóa raise.

Tuy nhiên, để tương thích ngược, chữ ký thứ hai được hỗ trợ, tuân theo quy ước từ các phiên bản Python cũ hơn. Đối số type phải là một lớp ngoại lệ và value phải là một trường hợp ngoại lệ. Nếu value không được cung cấp, hàm tạo type sẽ được gọi để lấy một phiên bản. Nếu traceback được cung cấp, nó sẽ được đặt ở dạng ngoại lệ, nếu không thì mọi thuộc tính __traceback__ hiện có được lưu trữ trong value đều có thể bị xóa.

Thay đổi trong phiên bản 3.12: Chữ ký thứ hai (type[, value[, traceback]]) không được dùng nữa và có thể bị xóa trong phiên bản Python trong tương lai.

generator.close()

Đưa ra một ngoại lệ GeneratorExit tại thời điểm chức năng tạo bị tạm dừng (tương đương với việc gọi throw(GeneratorExit)). Ngoại lệ được đưa ra bởi biểu thức lợi nhuận khi trình tạo bị tạm dừng. Nếu hàm tạo bắt được ngoại lệ và trả về một giá trị, giá trị này sẽ được trả về từ close(). Nếu hàm tạo đã bị đóng hoặc tăng GeneratorExit (bằng cách không bắt ngoại lệ), close() trả về None. Nếu trình tạo mang lại một giá trị, RuntimeError sẽ được nâng lên. Nếu trình tạo đưa ra bất kỳ ngoại lệ nào khác, nó sẽ được truyền tới người gọi. Nếu trình tạo đã thoát do ngoại lệ hoặc thoát bình thường, close() trả về None và không có tác dụng nào khác.

Thay đổi trong phiên bản 3.13: Nếu trình tạo trả về một giá trị khi bị đóng, giá trị đó sẽ được trả về bởi close().

6.2.10.2. Ví dụ

Dưới đây là một ví dụ đơn giản thể hiện hành vi của các trình tạo và các hàm tạo:

>>> def echo(value=None):
... print("Việc thực thi bắt đầu khi 'next()' được gọi lần đầu tiên.")
... thử:
... trong khi Đúng:
... thử:
... giá trị = (giá trị lợi nhuận)
... ngoại trừ Ngoại lệ  e:
... giá trị = e
... cuối cùng:
... print("Đừng quên dọn dẹp khi 'close()' được gọi.")
...
>>> máy phát điện = echo(1)
>>> in(tiếp theo(máy phát điện))
Quá trình thực thi bắt đầu khi 'next()' được gọi lần đầu tiên.
1
>>> in(tiếp theo(máy phát điện))
không có
>>> print(generator.send(2))
2
>>> Generator.throw(TypeError, "spam")
TypeError('thư rác',)
>>> máy phát điện.close()
Đừng quên dọn dẹp khi 'close()' được gọi.

Để biết ví dụ về cách sử dụng yield from, hãy xem PEP 380: Cú pháp ủy quyền cho Subgenerator trong "Có gì mới trong Python".

6.2.10.3. Chức năng tạo không đồng bộ

Sự hiện diện của biểu thức lợi nhuận trong một hàm hoặc phương thức được xác định bằng async def sẽ xác định thêm hàm đó là hàm asynchronous generator.

Khi một hàm tạo không đồng bộ được gọi, nó sẽ trả về một trình vòng lặp không đồng bộ được gọi là đối tượng trình tạo không đồng bộ. Đối tượng đó sau đó sẽ điều khiển việc thực thi hàm tạo. Đối tượng trình tạo không đồng bộ thường được sử dụng trong câu lệnh async for trong hàm coroutine tương tự như cách sử dụng đối tượng trình tạo trong câu lệnh for.

Việc gọi một trong các phương thức của trình tạo không đồng bộ sẽ trả về một đối tượng awaitable và quá trình thực thi bắt đầu khi đối tượng này được chờ đợi. Vào thời điểm đó, quá trình thực thi sẽ chuyển sang biểu thức lợi nhuận đầu tiên, tại đó nó lại bị tạm dừng, trả lại giá trị của yield_list cho coroutine đang chờ. Giống như một trình tạo, hệ thống treo có nghĩa là tất cả trạng thái cục bộ được giữ lại, bao gồm các ràng buộc hiện tại của các biến cục bộ, con trỏ lệnh, ngăn xếp đánh giá nội bộ và trạng thái xử lý bất kỳ ngoại lệ nào. Khi quá trình thực thi được tiếp tục bằng cách chờ đối tượng tiếp theo được các phương thức của trình tạo không đồng bộ trả về, hàm có thể tiến hành chính xác như thể biểu thức lợi nhuận chỉ là một lệnh gọi bên ngoài khác. Giá trị của biểu thức lợi nhuận sau khi tiếp tục phụ thuộc vào phương thức tiếp tục thực hiện. Nếu sử dụng __anext__() thì kết quả là None. Mặt khác, nếu asend() được sử dụng thì kết quả sẽ là giá trị được truyền vào phương thức đó.

Nếu trình tạo không đồng bộ tình cờ thoát sớm trước break, tác vụ của người gọi bị hủy hoặc các trường hợp ngoại lệ khác, mã dọn dẹp không đồng bộ của trình tạo sẽ chạy và có thể đưa ra các ngoại lệ hoặc truy cập các biến ngữ cảnh trong ngữ cảnh không mong muốn--có thể sau thời gian tồn tại của các tác vụ tùy thuộc vào hoặc trong khi tắt vòng lặp sự kiện khi móc thu gom rác của trình tạo không đồng bộ được gọi. Để ngăn chặn điều này, người gọi phải đóng trình tạo async một cách rõ ràng bằng cách gọi phương thức aclose() để hoàn thiện trình tạo và cuối cùng tách nó khỏi vòng lặp sự kiện.

Trong hàm tạo không đồng bộ, biểu thức lợi nhuận được phép ở bất kỳ đâu trong cấu trúc try. Tuy nhiên, nếu trình tạo không đồng bộ không được tiếp tục trước khi hoàn tất (bằng cách đạt đến số tham chiếu bằng 0 hoặc do bị thu gom rác), thì biểu thức lợi nhuận trong cấu trúc try có thể dẫn đến việc không thực thi được các mệnh đề finally đang chờ xử lý. Trong trường hợp này, trách nhiệm của vòng lặp sự kiện hoặc bộ lập lịch chạy trình tạo không đồng bộ là gọi phương thức aclose() của trình tạo vòng lặp không đồng bộ và chạy đối tượng coroutine kết quả, do đó cho phép mọi mệnh đề finally đang chờ xử lý thực thi.

Để xử lý việc hoàn thiện khi kết thúc vòng lặp sự kiện, vòng lặp sự kiện phải xác định hàm finalizer sử dụng trình lặp trình tạo không đồng bộ và có lẽ gọi aclose() và thực thi coroutine. Zz005zz này có thể được đăng ký bằng cách gọi sys.set_asyncgen_hooks(). Khi lặp lại lần đầu tiên, trình lặp trình tạo không đồng bộ sẽ lưu trữ finalizer đã đăng ký để gọi khi hoàn tất. Để biết ví dụ tham khảo về phương pháp finalizer, hãy xem cách triển khai asyncio.Loop.shutdown_asyncgens trong Lib/asyncio/base_events.py.

Biểu thức yield from <expr> là lỗi cú pháp khi được sử dụng trong hàm tạo không đồng bộ.

6.2.10.4. Các phương thức trình tạo-lặp không đồng bộ

Tiểu mục này mô tả các phương thức của trình lặp trình tạo không đồng bộ, được sử dụng để điều khiển việc thực thi hàm trình tạo.

async agen.__anext__()

Trả về một giá trị có thể chờ đợi mà khi chạy bắt đầu thực thi trình tạo không đồng bộ hoặc tiếp tục lại nó ở biểu thức lợi nhuận được thực hiện cuối cùng. Khi hàm tạo không đồng bộ được tiếp tục bằng phương thức __anext__(), biểu thức lợi nhuận hiện tại luôn ước tính thành None trong trạng thái chờ được trả về, biểu thức này khi chạy sẽ tiếp tục đến biểu thức lợi suất tiếp theo. Giá trị của yield_list của biểu thức lợi nhuận là giá trị của ngoại lệ StopIteration được đưa ra bởi coroutine hoàn chỉnh. Nếu trình tạo không đồng bộ thoát ra mà không mang lại giá trị khác, thì thay vào đó, có thể chờ đợi một ngoại lệ StopAsyncIteration, báo hiệu rằng quá trình lặp không đồng bộ đã hoàn thành.

Phương thức này thường được gọi ngầm bằng vòng lặp async for.

async agen.asend(value)

Trả về một giá trị có thể chờ đợi mà khi chạy sẽ tiếp tục thực thi trình tạo không đồng bộ. Giống như phương thức send() dành cho trình tạo, phương thức này "gửi" một giá trị vào hàm trình tạo không đồng bộ và đối số value trở thành kết quả của biểu thức lợi nhuận hiện tại. Giá trị chờ được trả về bởi phương thức asend() sẽ trả về giá trị tiếp theo do trình tạo mang lại dưới dạng giá trị của StopIteration được nâng lên hoặc tăng StopAsyncIteration nếu trình tạo không đồng bộ thoát ra mà không mang lại giá trị khác. Khi asend() được gọi để khởi động trình tạo không đồng bộ, nó phải được gọi với None làm đối số, vì không có biểu thức lợi nhuận nào có thể nhận giá trị.

async agen.athrow(value)
async agen.athrow(type[, value[, traceback]])

Trả về một đối tượng có thể chờ làm tăng ngoại lệ thuộc loại type tại thời điểm trình tạo không đồng bộ bị tạm dừng và trả về giá trị tiếp theo do hàm tạo mang lại làm giá trị của ngoại lệ StopIteration được nâng lên. Nếu trình tạo không đồng bộ thoát ra mà không mang lại giá trị khác, ngoại lệ StopAsyncIteration sẽ được đưa ra bởi giá trị chờ đợi. Nếu hàm tạo không bắt được ngoại lệ được truyền vào hoặc đưa ra một ngoại lệ khác, thì khi có thể chờ đợi được chạy, ngoại lệ đó sẽ truyền đến người gọi của đối tượng có thể chờ đợi đó.

Thay đổi trong phiên bản 3.12: Chữ ký thứ hai (type[, value[, traceback]]) không được dùng nữa và có thể bị xóa trong phiên bản Python trong tương lai.

async agen.aclose()

Trả về một giá trị có thể chờ đợi mà khi chạy sẽ ném GeneratorExit vào hàm tạo không đồng bộ tại thời điểm nó bị tạm dừng. Nếu sau đó hàm tạo không đồng bộ thoát ra một cách duyên dáng, đã đóng hoặc tăng GeneratorExit (bằng cách không bắt ngoại lệ), thì hàm chờ được trả về sẽ đưa ra ngoại lệ StopIteration. Bất kỳ điều gì có thể chờ đợi thêm được trả về bởi các cuộc gọi tiếp theo tới trình tạo không đồng bộ sẽ tạo ra ngoại lệ StopAsyncIteration. Nếu trình tạo không đồng bộ mang lại một giá trị, thì RuntimeError sẽ được nâng lên theo mức chờ đợi. Nếu trình tạo không đồng bộ đưa ra bất kỳ ngoại lệ nào khác, nó sẽ được truyền đến người gọi của đối tượng đang chờ. Nếu trình tạo không đồng bộ đã thoát do ngoại lệ hoặc thoát bình thường thì các lệnh gọi tiếp theo tới aclose() sẽ trả về một trạng thái chờ đợi mà không có tác dụng gì.

6.3. bầu cử sơ bộ

Các phần chính đại diện cho các hoạt động được ràng buộc chặt chẽ nhất của ngôn ngữ. Cú pháp của họ là:

primary: atom | attributeref | subscription | call

6.3.1. Tham chiếu thuộc tính

Tham chiếu thuộc tính là tham chiếu chính, theo sau là dấu chấm và tên:

attributeref: primary "." identifier

Chính phải đánh giá một đối tượng thuộc loại hỗ trợ tham chiếu thuộc tính, điều mà hầu hết các đối tượng đều làm. Đối tượng này sau đó được yêu cầu tạo ra thuộc tính có tên là định danh. Loại và giá trị được tạo ra được xác định bởi đối tượng. Nhiều đánh giá của cùng một tham chiếu thuộc tính có thể mang lại các đối tượng khác nhau.

Việc sản xuất này có thể được tùy chỉnh bằng cách ghi đè phương thức __getattribute__() hoặc phương thức __getattr__(). Phương thức __getattribute__() được gọi đầu tiên và trả về một giá trị hoặc tăng AttributeError nếu thuộc tính không có sẵn.

Nếu AttributeError được nâng lên và đối tượng có phương thức __getattr__() thì phương thức đó được gọi là phương thức dự phòng.

6.3.2. Đăng ký và cắt lát

Cú pháp subscription thường được sử dụng để chọn một phần tử từ container -- ví dụ: để lấy giá trị từ dict:

>>> chữ số_by_name = {'một': 1, 'hai': 2}
>>> chữ số_by_name['two'] # Subscripting một từ điển sử dụng phím 'two'
2

Trong cú pháp đăng ký, đối tượng được đăng ký -- primary -- được theo sau bởi subscript trong ngoặc vuông. Trong trường hợp đơn giản nhất, chỉ số dưới là một biểu thức duy nhất.

Tùy thuộc vào loại đối tượng được đăng ký, chỉ số dưới đôi khi được gọi là key (đối với ánh xạ), index (đối với chuỗi) hoặc type argument (đối với generic types). Về mặt cú pháp, tất cả đều tương đương:

>>> màu sắc = ['đỏ', 'xanh', 'xanh', 'đen']
>>> màu sắc[3] # Subscripting một danh sách sử dụng chỉ số 3
'đen'

>>> list[str] # Parameterizing loại danh sách sử dụng đối số loại str
danh sách[str]

Trong thời gian chạy, trình thông dịch sẽ đánh giá chỉ số chính và chỉ số dưới, đồng thời gọi __getitem__() hoặc __class_getitem__() special method của chính với chỉ số dưới làm đối số. Để biết thêm chi tiết về phương thức nào trong số này được gọi, hãy xem __class_getitem__ so với __getitem__.

Để hiển thị cách hoạt động của đăng ký, chúng ta có thể xác định một đối tượng tùy chỉnh triển khai __getitem__() và in ra giá trị của chỉ số dưới:

>>> Đăng  lớp Demo:
... def __getitem__(self, key):
... print(f'được đăng ký bằng: {key!r}')
...
>>> demo = Đăng kýDemo()
>>> bản trình diễn[1]
đã đăng ký với: 1
>>> demo['a' * 3]
được đăng ký với: 'aaa'

Xem tài liệu __getitem__() để biết cách xử lý các loại đăng ký tích hợp.

Đăng ký cũng có thể được sử dụng làm mục tiêu trong câu lệnh assignment hoặc deletion. Trong những trường hợp này, trình thông dịch sẽ gọi lần lượt là __setitem__() hoặc __delitem__() special method của đối tượng được chỉ số thay vì __getitem__().

>>> màu sắc = ['đỏ', 'xanh', 'xanh', 'đen']
>>> màu sắc [3] = 'màu trắng' mục # Setting ở chỉ mục
>>> màu sắc
['đỏ', 'xanh', 'xanh', 'trắng']
>>> del màu[3] mục # Deleting ở chỉ số 3
>>> màu sắc
['đỏ', 'xanh', 'xanh']

Tất cả các dạng subscript nâng cao được ghi lại trong các phần sau cũng có thể được sử dụng để gán và xóa.

6.3.2.1. Lát cắt

Một hình thức đăng ký nâng cao hơn, slicing, thường được sử dụng để trích xuất một phần của sequence. Ở dạng này, chỉ số dưới là slice: tối đa ba biểu thức được phân tách bằng dấu hai chấm. Bất kỳ biểu thức nào cũng có thể được bỏ qua, nhưng một lát cắt phải chứa ít nhất một dấu hai chấm:

>>> number_names = ['không', 'một', 'hai', 'ba', 'bốn', 'năm']
>>> số_names[1:3]
['một', 'hai']
>>> số_names[1:]
['một', 'hai', 'ba', 'bốn', 'năm']
>>> số_names[:3]
['không', 'một', 'hai']
>>> số_names[:]
['không', 'một', 'hai', 'ba', 'bốn', 'năm']
>>> số_names[::2]
['không', 'hai', 'bốn']
>>> số_names[:-3]
['không', 'một', 'hai']
>>> del number_names[4:]
>>> số_tên
['không', 'một', 'hai', 'ba']

Khi một lát cắt được đánh giá, trình thông dịch sẽ xây dựng một đối tượng slice có các thuộc tính start, stopstep tương ứng là kết quả của các biểu thức giữa các dấu hai chấm. Bất kỳ biểu thức bị thiếu nào đều có giá trị là None. Đối tượng slice này sau đó được chuyển đến __getitem__() hoặc __class_getitem__() special method, như trên.

# continuing với phiên bản SubscriptionDemo được xác định ở trên:
>>> bản trình diễn[2:3]
được đăng  bằng: slice(2, 3, None)
>>> demo[::'spam']
được đăng  bằng: slice(Không, Không, 'spam')

6.3.2.2. Chỉ số dưới được phân tách bằng dấu phẩy

Chỉ số dưới cũng có thể được đưa ra dưới dạng hai hoặc nhiều biểu thức hoặc lát cắt được phân tách bằng dấu phẩy

# continuing với phiên bản SubscriptionDemo được xác định ở trên:
>>> demo[1, 2, 3]
được đăng  bằng: (1, 2, 3)
>>> demo[1:2, 3]
được đăng  bằng: (slice(1, 2, None), 3)

Biểu mẫu này thường được sử dụng với các thư viện số để cắt dữ liệu đa chiều. Trong trường hợp này, trình thông dịch xây dựng một tuple kết quả của các biểu thức hoặc lát cắt và chuyển bộ dữ liệu này tới __getitem__() hoặc __class_getitem__() special method, như trên.

Chỉ số dưới cũng có thể được đưa ra dưới dạng một biểu thức hoặc một lát cắt theo sau là dấu phẩy, để chỉ định bộ dữ liệu một thành phần

>>> demo['spam',]
được đăng ký với: ('spam',)

6.3.2.3. Đăng ký "Có gắn dấu sao"

Added in version 3.11: Biểu thức trong tuple_slices có thể được gắn dấu sao. Xem PEP 646.

Chỉ số dưới cũng có thể chứa biểu thức được gắn dấu sao. Trong trường hợp này, trình thông dịch sẽ giải nén kết quả thành một bộ dữ liệu và chuyển bộ dữ liệu này tới __getitem__() hoặc __class_getitem__():

# continuing với phiên bản SubscriptionDemo được xác định ở trên:
>>> bản trình diễn[*phạm vi(10)]
được đăng  bằng: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

Các biểu thức được gắn dấu sao có thể được kết hợp với các biểu thức và lát cắt được phân tách bằng dấu phẩy:

>>> demo['a', 'b', *range(3), 'c']
được đăng ký bằng: ('a', 'b', 0, 1, 2, 'c')

6.3.2.4. Ngữ pháp đăng ký chính thức

subscription:     primary '[' subscript ']'
subscript:        single_subscript | tuple_subscript
single_subscript: proper_slice | assignment_expression
proper_slice:     [expression] ":" [expression] [ ":" [expression] ]
tuple_subscript:  ','.(single_subscript | starred_expression)+ [',']

Hãy nhớ lại rằng toán tử | denotes ordered choice. Cụ thể, trong subscript, nếu cả hai lựa chọn thay thế đều phù hợp thì phương án đầu tiên (single_subscript) được ưu tiên.

6.3.3. Cuộc gọi

Một cuộc gọi gọi một đối tượng có thể gọi được (ví dụ: function) với một chuỗi arguments có thể trống:

call:                 primary "(" [argument_list [","] | comprehension] ")"
argument_list:        positional_arguments ["," starred_and_keywords]
                        ["," keywords_arguments]
                      | starred_and_keywords ["," keywords_arguments]
                      | keywords_arguments
positional_arguments: positional_item ("," positional_item)*
positional_item:      assignment_expression | "*" expression
starred_and_keywords: ("*" expression | keyword_item)
                      ("," "*" expression | "," keyword_item)*
keywords_arguments:   (keyword_item | "**" expression)
                      ("," keyword_item | "," "**" expression)*
keyword_item:         identifier "=" expression

Dấu phẩy ở cuối tùy chọn có thể xuất hiện sau các đối số vị trí và từ khóa nhưng không ảnh hưởng đến ngữ nghĩa.

Chính phải đánh giá một đối tượng có thể gọi được (hàm do người dùng định nghĩa, hàm dựng sẵn, phương thức của đối tượng dựng sẵn, đối tượng lớp, phương thức của thể hiện lớp và tất cả các đối tượng có phương thức __call__() đều có thể gọi được). Tất cả các biểu thức đối số đều được đánh giá trước khi thực hiện cuộc gọi. Vui lòng tham khảo phần định nghĩa hàm để biết cú pháp của danh sách parameter chính thức.

Nếu có đối số từ khóa, trước tiên chúng sẽ được chuyển đổi thành đối số vị trí, như sau. Đầu tiên, một danh sách các vị trí chưa được lấp đầy sẽ được tạo cho các tham số chính thức. Nếu có N đối số vị trí, chúng sẽ được đặt vào N vị trí đầu tiên. Tiếp theo, đối với mỗi đối số từ khóa, mã định danh được sử dụng để xác định vị trí tương ứng (nếu mã định danh giống với tên tham số chính thức đầu tiên thì vị trí đầu tiên sẽ được sử dụng, v.v.). Nếu chỗ trống đã được lấp đầy, ngoại lệ TypeError sẽ xuất hiện. Ngược lại, đối số sẽ được đặt vào vị trí, lấp đầy nó (ngay cả khi biểu thức là None, nó sẽ lấp đầy vị trí đó). Khi tất cả các đối số đã được xử lý, các vị trí vẫn chưa được lấp đầy sẽ được lấp đầy bằng giá trị mặc định tương ứng từ định nghĩa hàm. (Các giá trị mặc định được tính toán một lần khi hàm được xác định; do đó, một đối tượng có thể thay đổi như danh sách hoặc từ điển được sử dụng làm giá trị mặc định sẽ được chia sẻ bởi tất cả các lệnh gọi không chỉ định giá trị đối số cho vị trí tương ứng; điều này thường nên tránh.) Nếu có bất kỳ vị trí nào chưa được lấp đầy mà không có giá trị mặc định nào được chỉ định, thì ngoại lệ TypeError sẽ xuất hiện. Ngược lại, danh sách các vị trí đã lấp đầy sẽ được sử dụng làm danh sách đối số cho cuộc gọi.

Việc triển khai có thể cung cấp các hàm dựng sẵn có tham số vị trí không có tên, ngay cả khi chúng được 'đặt tên' cho mục đích tài liệu và do đó không thể cung cấp theo từ khóa. Trong CPython, đây là trường hợp của các hàm được triển khai trong C sử dụng PyArg_ParseTuple() để phân tích các đối số của chúng.

Nếu có nhiều đối số vị trí hơn số khe tham số chính thức, một ngoại lệ TypeError sẽ được đưa ra, trừ khi có tham số chính thức sử dụng cú pháp *identifier; trong trường hợp này, tham số chính thức đó nhận được một bộ chứa các đối số vị trí dư thừa (hoặc một bộ trống nếu không có đối số vị trí dư thừa).

Nếu bất kỳ đối số từ khóa nào không tương ứng với tên tham số chính thức, một ngoại lệ TypeError sẽ được đưa ra, trừ khi có tham số chính thức sử dụng cú pháp **identifier; trong trường hợp này, tham số chính thức đó nhận được một từ điển chứa các đối số từ khóa dư thừa (sử dụng từ khóa làm khóa và giá trị đối số làm giá trị tương ứng) hoặc một từ điển trống (mới) nếu không có đối số từ khóa dư thừa.

Nếu cú ​​pháp *expression xuất hiện trong lệnh gọi hàm, expression phải đánh giá thành iterable. Các phần tử từ các lần lặp này được xử lý như thể chúng là các đối số vị trí bổ sung. Đối với lệnh gọi f(x1, x2, *y, x3, x4), nếu y đánh giá thành một chuỗi y1, ..., yM, thì điều này tương đương với lệnh gọi có M+4 đối số vị trí x1, x2, y1, ..., yM, x3, x4.

Hậu quả của việc này là mặc dù cú pháp *expression có thể xuất hiện các đối số từ khóa rõ ràng after, nhưng nó vẫn được xử lý before các đối số từ khóa (và mọi đối số **expression -- xem bên dưới). Vì vậy:

>>> định nghĩa f(a, b):
... in(a, b)
...
>>> f(b=1, *(2,))
2 1
>>> f(a=1, *(2,))
Traceback (cuộc gọi gần đây nhất):
  Tệp "<stdin>", dòng 1, trong <module>
TypeError: f() có nhiều giá trị cho đối số từ khóa 'a'
>>> f(1, *(2,))
1 2

Điều bất thường là cả đối số từ khóa và cú pháp *expression đều được sử dụng trong cùng một lệnh gọi, vì vậy trong thực tế, sự nhầm lẫn này không thường xuyên xảy ra.

Nếu cú pháp **expression xuất hiện trong lệnh gọi hàm, expression phải đánh giá thành mapping, nội dung của nó được coi là đối số từ khóa bổ sung. Nếu một tham số khớp với khóa đã được cung cấp một giá trị (bởi một đối số từ khóa rõ ràng hoặc từ một lần giải nén khác), thì ngoại lệ TypeError sẽ xuất hiện.

Khi sử dụng **expression, mỗi khóa trong ánh xạ này phải là một chuỗi. Mỗi giá trị từ ánh xạ được gán cho tham số chính thức đầu tiên đủ điều kiện để gán từ khóa có tên bằng khóa. Khóa không cần phải là mã định danh Python (ví dụ: "max-temp °F" có thể được chấp nhận, mặc dù nó sẽ không khớp với bất kỳ tham số chính thức nào có thể được khai báo). Nếu không có kết quả khớp với tham số chính thức thì cặp khóa-giá trị sẽ được tham số ** thu thập, nếu có hoặc nếu không có, ngoại lệ TypeError sẽ được đưa ra.

Không thể sử dụng các tham số chính thức sử dụng cú pháp *identifier hoặc **identifier làm vị trí đối số vị trí hoặc làm tên đối số từ khóa.

Thay đổi trong phiên bản 3.5: Các lệnh gọi hàm chấp nhận bất kỳ số lần giải nén *** nào, các đối số vị trí có thể theo sau các lần giải nén lặp lại (*) và các đối số từ khóa có thể tuân theo các lần giải nén từ điển (**). Ban đầu được đề xuất bởi PEP 448.

Cuộc gọi luôn trả về một giá trị nào đó, có thể là None, trừ khi nó đưa ra một ngoại lệ. Giá trị này được tính như thế nào tùy thuộc vào loại đối tượng có thể gọi được.

Nếu là---

một hàm do người dùng xác định:

Khối mã cho hàm được thực thi, chuyển cho nó danh sách đối số. Điều đầu tiên khối mã sẽ làm là liên kết các tham số hình thức với các đối số; điều này được mô tả trong phần định nghĩa hàm. Khi khối mã thực thi câu lệnh return, điều này chỉ định giá trị trả về của lệnh gọi hàm. Nếu quá trình thực thi đến cuối khối mã mà không thực hiện câu lệnh return thì giá trị trả về là None.

một hàm hoặc phương thức tích hợp sẵn:

Kết quả tùy thuộc vào người phiên dịch; xem Chức năng tích hợp để biết mô tả về các hàm và phương thức tích hợp.

một đối tượng lớp:

Một phiên bản mới của lớp đó được trả về.

một phương thức cá thể của lớp:

Hàm do người dùng xác định tương ứng được gọi, với danh sách đối số dài hơn danh sách đối số của lệnh gọi: phiên bản này trở thành đối số đầu tiên.

một thể hiện của lớp:

Lớp phải xác định phương thức __call__(); hiệu ứng sau đó giống như khi phương thức đó được gọi.

6.4. Đang chờ biểu thức

Tạm dừng việc thực thi coroutine trên đối tượng awaitable. Chỉ có thể được sử dụng bên trong coroutine function.

await_expr: "await" primary

Added in version 3.5.

6.5. Người vận hành điện

Toán tử lũy thừa liên kết chặt chẽ hơn toán tử một ngôi ở bên trái của nó; nó liên kết ít chặt chẽ hơn các toán tử đơn nguyên ở bên phải. Cú pháp là:

power: (await_expr | primary) ["**" u_expr]

Do đó, trong một chuỗi các toán tử lũy thừa và một ngôi không được đóng ngoặc đơn, các toán tử được đánh giá từ phải sang trái (điều này không hạn chế thứ tự đánh giá cho các toán hạng): -1**2 dẫn đến -1.

Toán tử lũy thừa có ngữ nghĩa giống như hàm pow() tích hợp sẵn, khi được gọi với hai đối số: nó mang lại đối số bên trái được nâng lên lũy thừa của đối số bên phải. Đối số số đầu tiên là converted to a common type và kết quả thuộc loại đó.

Đối với toán hạng int, kết quả có cùng loại với toán hạng trừ khi đối số thứ hai là số âm; trong trường hợp đó, tất cả các đối số được chuyển đổi thành float và kết quả float được phân phối. Ví dụ: 10**2 trả về 100, nhưng 10**-2 trả về 0.01.

Tăng 0.0 lên lũy thừa âm sẽ tạo ra ZeroDivisionError. Việc nâng số âm lên lũy thừa phân số sẽ tạo ra số complex. (Trong các phiên bản trước, nó đã đưa ra ValueError.)

Hoạt động này có thể được tùy chỉnh bằng các phương pháp __pow__()__rpow__() đặc biệt.

6.6. Các phép toán số học đơn nhất và bitwise

Tất cả các phép toán số học đơn phân và bitwise đều có cùng mức độ ưu tiên:

u_expr: power | "-" u_expr | "+" u_expr | "~" u_expr

Toán tử - (trừ) đơn nhất mang lại sự phủ định đối số số của nó; thao tác có thể được ghi đè bằng phương thức đặc biệt __neg__().

Toán tử + (cộng) đơn nhất mang lại đối số số không thay đổi; thao tác có thể được ghi đè bằng phương thức đặc biệt __pos__().

Toán tử ~ (đảo ngược) đơn nhất mang lại phép đảo ngược bit đối số nguyên của nó. Đảo ngược bitwise của x được định nghĩa là -(x+1). Nó chỉ áp dụng cho các số nguyên hoặc cho các đối tượng tùy chỉnh ghi đè phương thức đặc biệt __invert__().

Trong cả ba trường hợp, nếu đối số không có loại thích hợp thì ngoại lệ TypeError sẽ xuất hiện.

6.7. Các phép toán số học nhị phân

Các phép toán số học nhị phân có mức độ ưu tiên thông thường. Lưu ý rằng một số thao tác này cũng áp dụng cho một số loại không phải số. Ngoài toán tử lũy thừa, chỉ có hai cấp độ, một dành cho toán tử nhân và một dành cho toán tử cộng:

m_expr: u_expr | m_expr "*" u_expr | m_expr "@" m_expr |
        m_expr "//" u_expr | m_expr "/" u_expr |
        m_expr "%" u_expr
a_expr: m_expr | a_expr "+" m_expr | a_expr "-" m_expr

Toán tử * (phép nhân) mang lại tích của các đối số của nó. Các đối số phải đều là số hoặc một đối số phải là số nguyên và đối số kia phải là một chuỗi. Trong trường hợp trước, các số là converted to a common real type rồi nhân với nhau. Trong trường hợp sau, việc lặp lại trình tự được thực hiện; hệ số lặp âm mang lại một chuỗi trống.

Hoạt động này có thể được tùy chỉnh bằng các phương pháp __mul__()__rmul__() đặc biệt.

Thay đổi trong phiên bản 3.14: Nếu chỉ có một toán hạng là số phức thì toán hạng còn lại sẽ được chuyển thành số dấu phẩy động.

Toán tử @ (at) được dùng để nhân ma trận. Không có kiểu Python dựng sẵn nào triển khai toán tử này.

Hoạt động này có thể được tùy chỉnh bằng các phương pháp __matmul__()__rmatmul__() đặc biệt.

Added in version 3.5.

Các toán tử / (chia) và // (chia sàn) mang lại thương số cho các đối số của chúng. Các đối số số đầu tiên là converted to a common type. Phép chia số nguyên mang lại kết quả là số float, trong khi phép chia số nguyên sàn cho kết quả là số nguyên; kết quả là phép chia toán học với hàm 'sàn' được áp dụng cho kết quả. Chia cho số 0 sẽ tạo ra ngoại lệ ZeroDivisionError.

Hoạt động chia có thể được tùy chỉnh bằng cách sử dụng các phương pháp __truediv__()__rtruediv__() đặc biệt. Hoạt động phân chia tầng có thể được tùy chỉnh bằng các phương pháp __floordiv__()__rfloordiv__() đặc biệt.

Toán tử % (modulo) mang lại phần còn lại từ việc chia đối số đầu tiên cho đối số thứ hai. Các đối số số đầu tiên là converted to a common type. Đối số 0 bên phải sẽ gây ra ngoại lệ ZeroDivisionError. Các đối số có thể là số dấu phẩy động, ví dụ: 3.14%0.7 bằng 0.34 (vì 3.14 bằng 4*0.7 + 0.34.) Toán tử modulo luôn mang lại kết quả có cùng dấu với toán hạng thứ hai (hoặc 0); giá trị tuyệt đối của kết quả nhỏ hơn giá trị tuyệt đối của toán hạng thứ hai [1].

Các toán tử phân chia sàn và modulo được kết nối bằng mã nhận dạng sau: x == (x//y)*y + (x%y). Phân chia tầng và modulo cũng được kết nối với chức năng tích hợp divmod(): divmod(x, y) == (x//y, x%y). [2].

Ngoài việc thực hiện phép toán modulo trên số, toán tử % còn bị các đối tượng chuỗi làm quá tải để thực hiện định dạng chuỗi kiểu cũ (còn được gọi là nội suy). Cú pháp định dạng chuỗi được mô tả trong Tham khảo Thư viện Python, phần Định dạng chuỗi kiểu printf.

Hoạt động modulo có thể được tùy chỉnh bằng các phương pháp __mod__()__rmod__() đặc biệt.

Toán tử chia sàn, toán tử modulo và hàm divmod() không được xác định cho số phức. Thay vào đó, hãy chuyển đổi sang số dấu phẩy động bằng hàm abs() nếu thích hợp.

Toán tử + (cộng) mang lại tổng các đối số của nó. Các đối số phải là số hoặc cả hai đều là chuỗi cùng loại. Trong trường hợp trước, các số là converted to a common real type và sau đó được cộng lại với nhau. Trong trường hợp sau, các chuỗi được nối với nhau.

Hoạt động này có thể được tùy chỉnh bằng các phương pháp __add__()__radd__() đặc biệt.

Thay đổi trong phiên bản 3.14: Nếu chỉ có một toán hạng là số phức thì toán hạng còn lại sẽ được chuyển thành số dấu phẩy động.

Toán tử - (trừ) mang lại hiệu của các đối số của nó. Các đối số số đầu tiên là converted to a common real type.

Hoạt động này có thể được tùy chỉnh bằng các phương pháp __sub__()__rsub__() đặc biệt.

Thay đổi trong phiên bản 3.14: Nếu chỉ có một toán hạng là số phức thì toán hạng còn lại sẽ được chuyển thành số dấu phẩy động.

6.8. Hoạt động chuyển dịch

Các phép toán dịch chuyển có mức độ ưu tiên thấp hơn các phép toán số học:

shift_expr: a_expr | shift_expr ("<<" | ">>") a_expr

Các toán tử này chấp nhận số nguyên làm đối số. Họ dịch chuyển đối số thứ nhất sang trái hoặc phải theo số bit do đối số thứ hai cung cấp.

Hoạt động dịch chuyển trái có thể được tùy chỉnh bằng cách sử dụng các phương pháp __lshift__()__rlshift__() đặc biệt. Hoạt động dịch chuyển bên phải có thể được tùy chỉnh bằng cách sử dụng các phương pháp __rshift__()__rrshift__() đặc biệt.

Sự dịch chuyển sang phải theo các bit n được định nghĩa là phép chia tầng cho pow(2,n). Sự dịch chuyển trái của các bit n được định nghĩa là phép nhân với pow(2,n).

6.9. Hoạt động bitwise nhị phân

Mỗi thao tác trong số ba thao tác bitwise có mức độ ưu tiên khác nhau:

and_expr: shift_expr | and_expr "&" shift_expr
xor_expr: and_expr | xor_expr "^" and_expr
or_expr:  xor_expr | or_expr "|" xor_expr

Toán tử & mang lại AND theo bit cho các đối số của nó, các đối số này phải là số nguyên hoặc một trong số chúng phải là đối tượng tùy chỉnh ghi đè các phương thức đặc biệt __and__() hoặc __rand__().

Toán tử ^ mang lại XOR bitwise (OR độc quyền) cho các đối số của nó, các đối số này phải là số nguyên hoặc một trong số chúng phải là đối tượng tùy chỉnh ghi đè các phương thức đặc biệt __xor__() hoặc __rxor__().

Toán tử | mang lại OR theo bit (bao gồm) OR của các đối số của nó, phải là số nguyên hoặc một trong số chúng phải là đối tượng tùy chỉnh ghi đè các phương thức đặc biệt __or__() hoặc __ror__().

6.10. So sánh

Không giống như C, tất cả các phép toán so sánh trong Python đều có cùng mức độ ưu tiên, thấp hơn so với bất kỳ phép toán số học, dịch chuyển hoặc bitwise nào. Cũng không giống như C, các biểu thức như a < b < c có cách giải thích thông thường trong toán học:

comparison:    or_expr (comp_operator or_expr)*
comp_operator: "<" | ">" | "==" | ">=" | "<=" | "!="
               | "is" ["not"] | ["not"] "in"

So sánh mang lại giá trị boolean: True hoặc False. rich comparison methods tùy chỉnh có thể trả về các giá trị không phải boolean. Trong trường hợp này Python sẽ gọi bool() với giá trị như vậy trong bối cảnh boolean.

Các phép so sánh có thể được xâu chuỗi tùy ý, ví dụ: x < y <= z tương đương với x < y and y <= z, ngoại trừ việc y chỉ được đánh giá một lần (nhưng trong cả hai trường hợp, z hoàn toàn không được đánh giá khi x < y được phát hiện là sai).

Về mặt hình thức, nếu a, b, c, ..., y, z là các biểu thức và op1, op2, ..., opN là các toán tử so sánh thì a op1 b op2 c ... y opN z tương đương với a op1 b and b op2 c and ... y opN z, ngoại trừ việc mỗi biểu thức được đánh giá nhiều nhất một lần.

Lưu ý rằng a op1 b op2 c không ngụ ý bất kỳ hình thức so sánh nào giữa ac, do đó, ví dụ: x < y > z là hoàn toàn hợp pháp (mặc dù có lẽ không đẹp).

6.10.1. So sánh giá trị

Các toán tử <, >, ==, >=, <=!= so sánh giá trị của hai đối tượng. Các đối tượng không cần phải có cùng loại.

Chương Đối tượng, giá trị và loại nói rằng các đối tượng có một giá trị (ngoài loại và danh tính). Giá trị của một đối tượng là một khái niệm khá trừu tượng trong Python: Ví dụ: không có phương thức truy cập chuẩn nào cho giá trị của đối tượng. Ngoài ra, không có yêu cầu nào về giá trị của một đối tượng phải được xây dựng theo một cách cụ thể, ví dụ: bao gồm tất cả các thuộc tính dữ liệu của nó. Các toán tử so sánh thực hiện một khái niệm cụ thể về giá trị của một đối tượng. Người ta có thể coi chúng như việc xác định giá trị của một đối tượng một cách gián tiếp, bằng cách thực hiện so sánh của chúng.

Vì tất cả các loại đều là kiểu con (trực tiếp hoặc gián tiếp) của object nên chúng kế thừa hành vi so sánh mặc định từ object. Các loại có thể tùy chỉnh hành vi so sánh của chúng bằng cách triển khai rich comparison methods như __lt__(), được mô tả trong Tùy chỉnh cơ bản.

Hành vi mặc định để so sánh đẳng thức (==!=) dựa trên danh tính của các đối tượng. Do đó, so sánh đẳng thức của các thể hiện có cùng danh tính sẽ dẫn đến đẳng thức và so sánh đẳng thức của các thể hiện với các danh tính khác nhau sẽ dẫn đến bất bình đẳng. Động lực cho hành vi mặc định này là mong muốn rằng tất cả các đối tượng phải có tính phản xạ (tức là x is y ngụ ý x == y).

So sánh thứ tự mặc định (<, >, <=>=) không được cung cấp; một nỗ lực sẽ tăng TypeError. Động lực cho hành vi mặc định này là do thiếu một bất biến tương tự như đối với sự bình đẳng.

Hành vi của so sánh đẳng thức mặc định, trong đó các trường hợp có danh tính khác nhau luôn không bằng nhau, có thể trái ngược với những loại sẽ cần có định nghĩa hợp lý về giá trị đối tượng và đẳng thức dựa trên giá trị. Những loại như vậy sẽ cần phải tùy chỉnh hành vi so sánh của chúng và trên thực tế, một số loại tích hợp đã thực hiện được điều đó.

Danh sách sau đây mô tả hành vi so sánh của các loại tích hợp quan trọng nhất.

  • Số lượng các loại số tích hợp (Các loại số --- int, float, complex) và các loại thư viện tiêu chuẩn fractions.Fractiondecimal.Decimal có thể được so sánh trong và giữa các loại của chúng, với hạn chế là các số phức không hỗ trợ so sánh thứ tự. Trong giới hạn của các loại liên quan, chúng so sánh chính xác về mặt toán học (thuật toán) mà không làm mất độ chính xác.

    Các giá trị không phải số float('NaN')decimal.Decimal('NaN') là đặc biệt. Mọi so sánh có thứ tự của một số với một giá trị không phải là số đều sai. Một hàm ý phản trực giác là các giá trị không phải là số không bằng chính chúng. Ví dụ: nếu x = float('NaN'), 3 < x, x < 3x == x đều sai, trong khi x != x là đúng. Hành vi này tuân thủ IEEE 754.

  • NoneNotImplemented là những singletons. PEP 8 khuyên rằng việc so sánh các singleton phải luôn được thực hiện với is hoặc is not, không bao giờ sử dụng các toán tử đẳng thức.

  • Các chuỗi nhị phân (các phiên bản của bytes hoặc bytearray) có thể được so sánh trong và giữa các loại của chúng. Họ so sánh từ điển bằng cách sử dụng các giá trị số của các phần tử của chúng.

  • Các chuỗi (phiên bản của str) so sánh từ điển bằng cách sử dụng các điểm mã Unicode số (kết quả của hàm tích hợp ord()) của các ký tự của chúng. [3]

    Chuỗi và chuỗi nhị phân không thể so sánh trực tiếp.

  • Các chuỗi (các phiên bản của tuple, list hoặc range) chỉ có thể được so sánh trong mỗi loại của chúng, với hạn chế là các phạm vi không hỗ trợ so sánh thứ tự. So sánh bình đẳng giữa các loại này dẫn đến bất bình đẳng và so sánh thứ tự giữa các loại này làm tăng TypeError.

    Trình tự so sánh theo từ điển bằng cách sử dụng so sánh các phần tử tương ứng. Các thùng chứa tích hợp thường cho rằng các đối tượng giống hệt nhau đều bằng chính chúng. Điều đó cho phép chúng bỏ qua các bài kiểm tra tính bằng nhau đối với các đối tượng giống hệt nhau để cải thiện hiệu suất và duy trì các bất biến bên trong của chúng.

    So sánh từ điển giữa các bộ sưu tập tích hợp hoạt động như sau:

    • Để hai bộ sưu tập có thể so sánh bằng nhau, chúng phải cùng loại, có cùng độ dài và mỗi cặp phần tử tương ứng phải so sánh bằng nhau (ví dụ: [1,2] == (1,2) là sai vì loại không giống nhau).

    • Các bộ sưu tập hỗ trợ so sánh thứ tự được sắp xếp giống như các phần tử không bằng nhau đầu tiên của chúng (ví dụ: [1,2,x] <= [1,2,y] có cùng giá trị với x <= y). Nếu phần tử tương ứng không tồn tại, bộ sưu tập ngắn hơn sẽ được sắp xếp trước (ví dụ: [1,2] < [1,2,3] là đúng).

  • Ánh xạ (các phiên bản của dict) so sánh bằng nhau khi và chỉ khi chúng có các cặp (key, value) bằng nhau. So sánh bình đẳng giữa các khóa và giá trị thực thi tính phản xạ.

    So sánh thứ tự (<, >, <=>=) nâng cao TypeError.

  • Các bộ (phiên bản của set hoặc frozenset) có thể được so sánh trong và giữa các loại của chúng.

    Họ định nghĩa các toán tử so sánh thứ tự có nghĩa là các thử nghiệm tập hợp con và tập hợp con. Các mối quan hệ đó không xác định tổng thứ tự (ví dụ: hai bộ {1,2}{2,3} không bằng nhau, cũng như các tập hợp con của nhau, cũng như các tập hợp siêu của nhau). Theo đó, các tập hợp không phải là đối số thích hợp cho các hàm phụ thuộc vào tổng thứ tự (ví dụ: min(), max()sorted() tạo ra các kết quả không xác định dựa trên danh sách các tập hợp làm đầu vào).

    So sánh các tập hợp thực thi tính phản xạ của các phần tử của nó.

  • Hầu hết các loại tích hợp khác không có phương pháp so sánh nào được triển khai, vì vậy chúng kế thừa hành vi so sánh mặc định.

Các lớp do người dùng định nghĩa tùy chỉnh hành vi so sánh của chúng phải tuân theo một số quy tắc nhất quán, nếu có thể:

  • So sánh bình đẳng nên mang tính phản ánh. Nói cách khác, các đối tượng giống hệt nhau nên so sánh bằng nhau:

    x is y ngụ ý x == y

  • So sánh phải đối xứng. Nói cách khác, các biểu thức sau sẽ có cùng kết quả:

    x == yy == x

    x != yy != x

    x < yy > x

    x <= yy >= x

  • So sánh nên mang tính bắc cầu. Các ví dụ sau (không đầy đủ) minh họa điều đó:

    x > y and y > z ngụ ý x > z

    x < y and y <= z ngụ ý x < z

  • So sánh nghịch đảo sẽ dẫn đến phủ định boolean. Nói cách khác, các biểu thức sau sẽ có cùng kết quả:

    x == ynot x != y

    x < ynot x >= y (cho tổng số đơn đặt hàng)

    x > ynot x <= y (cho tổng số đơn đặt hàng)

    Hai biểu thức cuối cùng áp dụng cho các bộ sưu tập được sắp xếp hoàn toàn (ví dụ: cho các chuỗi, nhưng không áp dụng cho các tập hợp hoặc ánh xạ). Xem thêm phần trang trí total_ordering().

  • Kết quả hash() phải nhất quán với sự bình đẳng. Các đối tượng bằng nhau phải có cùng giá trị băm hoặc được đánh dấu là không thể băm.

Python không thực thi các quy tắc nhất quán này. Trên thực tế, các giá trị không phải là số là một ví dụ về việc không tuân theo các quy tắc này.

6.10.2. Hoạt động kiểm tra tư cách thành viên

Các nhà khai thác innot in kiểm tra tư cách thành viên. x in s đánh giá là True nếu x là thành viên của sFalse nếu ngược lại. x not in s trả về phủ định của x in s. Tất cả các chuỗi và kiểu tập hợp tích hợp đều hỗ trợ điều này cũng như từ điển, trong đó in kiểm tra xem từ điển có khóa nhất định hay không. Đối với các loại vùng chứa như danh sách, bộ dữ liệu, bộ, Frozenset, dict hoặc Collection.deque, biểu thức x in y tương đương với any(x is e or x == e for e in y).

Đối với loại chuỗi và byte, x in yTrue khi và chỉ khi x là chuỗi con của y. Một bài kiểm tra tương đương là y.find(x) != -1. Các chuỗi rỗng luôn được coi là chuỗi con của bất kỳ chuỗi nào khác, vì vậy "" in "abc" sẽ trả về True.

Đối với các lớp do người dùng định nghĩa xác định phương thức __contains__(), x in y trả về True nếu y.__contains__(x) trả về giá trị đúng và False nếu không.

Đối với các lớp do người dùng định nghĩa không xác định __contains__() nhưng xác định __iter__(), x in yTrue nếu một số giá trị z, mà biểu thức x is z or x == z là đúng, được tạo ra trong khi lặp qua y. Nếu một ngoại lệ được đưa ra trong quá trình lặp lại, thì có vẻ như in đã đưa ra ngoại lệ đó.

Cuối cùng, giao thức lặp kiểu cũ được thử: nếu một lớp định nghĩa __getitem__(), x in yTrue khi và chỉ khi có chỉ số nguyên không âm i sao cho x is y[i] or x == y[i] và không có chỉ số nguyên nào thấp hơn làm tăng ngoại lệ IndexError. (Nếu bất kỳ ngoại lệ nào khác được đưa ra, thì giống như in đã đưa ra ngoại lệ đó).

Toán tử not in được xác định có giá trị thực nghịch đảo của in.

6.10.3. So sánh danh tính

Các toán tử isis not kiểm tra danh tính của một đối tượng: x is y đúng khi và chỉ nếu xy là cùng một đối tượng. Danh tính của Đối tượng được xác định bằng hàm id(). x is not y mang lại giá trị chân lý nghịch đảo. [4]

6.11. Các phép toán Boolean

or_test:  and_test | or_test "or" and_test
and_test: not_test | and_test "and" not_test
not_test: comparison | "not" not_test

Trong ngữ cảnh của các phép toán Boolean cũng như khi các biểu thức được sử dụng bởi câu lệnh luồng điều khiển, các giá trị sau được hiểu là sai: False, None, số 0 thuộc tất cả các loại cũng như các chuỗi và vùng chứa trống (bao gồm chuỗi, bộ dữ liệu, danh sách, từ điển, bộ và tập hợp đông lạnh). Tất cả các giá trị khác được hiểu là đúng. Các đối tượng do người dùng xác định có thể tùy chỉnh giá trị thực của chúng bằng cách cung cấp phương thức __bool__().

Toán tử not mang lại True nếu đối số của nó sai, False nếu ngược lại.

Biểu thức x and y đầu tiên đánh giá x; nếu x sai, giá trị của nó sẽ được trả về; nếu không, y sẽ được đánh giá và trả về giá trị kết quả.

Biểu thức x or y đầu tiên đánh giá x; nếu x đúng, giá trị của nó sẽ được trả về; nếu không, y sẽ được đánh giá và trả về giá trị kết quả.

Lưu ý rằng cả andor đều không hạn chế giá trị và loại mà chúng trả về FalseTrue mà trả về đối số được đánh giá cuối cùng. Điều này đôi khi hữu ích, ví dụ: nếu s là một chuỗi cần được thay thế bằng một giá trị mặc định nếu nó trống, thì biểu thức s or 'foo' sẽ mang lại giá trị mong muốn. Vì not phải tạo một giá trị mới nên nó trả về giá trị boolean bất kể loại đối số của nó là gì (ví dụ: not 'foo' tạo ra False chứ không phải ''.)

6.12. biểu thức gán

assignment_expression: [identifier ":="] expression

Một biểu thức gán (đôi khi còn được gọi là "biểu thức được đặt tên" hoặc "hải mã") gán expression cho identifier, đồng thời trả về giá trị của expression.

Một trường hợp sử dụng phổ biến là khi xử lý các biểu thức chính quy phù hợp:

nếu khớp := mẫu.search(dữ liệu):
    do_something(khớp)

Hoặc, khi xử lý luồng tệp theo từng đoạn:

trong khi chunk := file.read(9000):
    quá trình (đoạn)

Biểu thức gán phải được bao quanh bởi dấu ngoặc đơn khi được sử dụng làm câu lệnh biểu thức và khi được dùng làm biểu thức phụ trong các biểu thức cắt, điều kiện, lambda, đối số từ khóa và hiểu-if cũng như trong các câu lệnh assert, withassignment. Ở tất cả những nơi khác có thể sử dụng chúng, không cần có dấu ngoặc đơn, kể cả trong câu lệnh ifwhile.

Added in version 3.8: Xem PEP 572 để biết thêm chi tiết về biểu thức gán.

6.13. biểu thức điều kiện

conditional_expression: or_test ["if" or_test "else" expression]
expression:             conditional_expression | lambda_expr

Biểu thức điều kiện (đôi khi được gọi là "toán tử ba ngôi") là một thay thế cho câu lệnh if-else. Vì là một biểu thức nên nó trả về một giá trị và có thể xuất hiện dưới dạng biểu thức phụ.

Biểu thức x if C else y đầu tiên đánh giá điều kiện, C thay vì x. Nếu C đúng, x được đánh giá và trả về giá trị của nó; nếu không, y sẽ được đánh giá và trả về giá trị của nó.

Xem PEP 308 để biết thêm chi tiết về biểu thức điều kiện.

6.14. Lambda

lambda_expr: "lambda" [parameter_list] ":" expression

Biểu thức Lambda (đôi khi được gọi là biểu mẫu lambda) được sử dụng để tạo các hàm ẩn danh. Biểu thức lambda parameters: expression mang lại một đối tượng hàm. Đối tượng không tên hoạt động giống như một đối tượng hàm được xác định bằng:

def <lambda>(tham số):
    biểu thức trả về

Xem phần định nghĩa hàm để biết cú pháp của danh sách tham số. Lưu ý rằng các hàm được tạo bằng biểu thức lambda không thể chứa các câu lệnh hoặc chú thích.

6.15. Danh sách biểu thức

starred_expression:       "*" or_expr | expression
flexible_expression:      assignment_expression | starred_expression
flexible_expression_list: flexible_expression ("," flexible_expression)* [","]
starred_expression_list:  starred_expression ("," starred_expression)* [","]
expression_list:          expression ("," expression)* [","]
yield_list:               expression_list | starred_expression "," [starred_expression_list]

Ngoại trừ khi một phần của danh sách hoặc tập hợp hiển thị, danh sách biểu thức chứa ít nhất một dấu phẩy sẽ tạo ra một bộ dữ liệu. Độ dài của bộ dữ liệu là số lượng biểu thức trong danh sách. Các biểu thức được đánh giá từ trái sang phải.

Dấu hoa thị * biểu thị iterable unpacking. Toán hạng của nó phải là iterable. Iterable được mở rộng thành một chuỗi các mục, được bao gồm trong bộ dữ liệu, danh sách hoặc bộ mới, tại vị trí giải nén.

Added in version 3.5: Giải nén lặp lại trong danh sách biểu thức, ban đầu được đề xuất bởi PEP 448.

Added in version 3.11: Bất kỳ mục nào trong danh sách biểu thức đều có thể được gắn dấu sao. Xem PEP 646.

Chỉ cần có dấu phẩy ở cuối để tạo bộ dữ liệu một mục, chẳng hạn như 1,; nó là tùy chọn trong tất cả các trường hợp khác. Một biểu thức không có dấu phẩy ở cuối sẽ không tạo ra một bộ dữ liệu mà mang lại giá trị của biểu thức đó. (Để tạo một bộ trống, hãy sử dụng một cặp dấu ngoặc đơn trống: ().)

6.16. Thứ tự đánh giá

Python đánh giá các biểu thức từ trái sang phải. Lưu ý rằng khi đánh giá một bài tập, vế phải được đánh giá trước vế trái.

Trong các dòng sau, các biểu thức sẽ được đánh giá theo thứ tự số học của các hậu tố của chúng:

expr1, expr2, expr3, expr4
(expr1, expr2, expr3, expr4)
{expr1: expr2, expr3: expr4}
expr1 + expr2 * (expr3 - expr4)
expr1(expr2, expr3, *expr4, **expr5)
expr3, expr4 = expr1, expr2

6.17. Ưu tiên toán tử

Bảng sau đây tóm tắt mức độ ưu tiên của toán tử trong Python, từ mức độ ưu tiên cao nhất (ràng buộc nhiều nhất) đến mức độ ưu tiên thấp nhất (ít ràng buộc nhất). Các toán tử trong cùng một hộp có mức độ ưu tiên như nhau. Trừ khi cú pháp được đưa ra rõ ràng, các toán tử là nhị phân. Các toán tử trong cùng một ô được nhóm từ trái sang phải (trừ biểu thức lũy thừa và biểu thức điều kiện, nhóm nào từ phải sang trái).

Lưu ý rằng các so sánh, kiểm tra tư cách thành viên và kiểm tra danh tính, tất cả đều có cùng mức độ ưu tiên và có tính năng xâu chuỗi từ trái sang phải như được mô tả trong phần So sánh.

Toán tử

Mô tả

(expressions...),

[expressions...], {key: value...}, {expressions...}

Biểu thức liên kết hoặc ngoặc đơn, hiển thị danh sách, hiển thị từ điển, hiển thị tập hợp

x[index], x[index:index] x(arguments...), x.attribute

Đăng ký (bao gồm cả cắt), cuộc gọi, tham chiếu thuộc tính

await x

Đang chờ biểu thức

**

Lũy thừa [5]

+x, -x, ~x

Tích cực, tiêu cực, bitwise NOT

*, @, /, //, %

Phép nhân, phép nhân ma trận, phép chia, phép chia sàn, số dư [6]

+, -

Cộng và trừ

<<, >>

ca

&

Bitwise AND

^

Bitwise XOR

|

Theo bit HOẶC

in, not in, is, is not, <, <=, >, >=, !=, ==

So sánh, bao gồm kiểm tra thành viên và kiểm tra danh tính

not x

Boolean NOT

and

Boolean AND

or

Boolean HOẶC

if -- else

biểu thức có điều kiện

lambda

Biểu thức Lambda

:=

biểu thức bài tập

Chú thích cuối trang