<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ### 導航 - [索引](../genindex.xhtml "總目錄") - [模塊](../py-modindex.xhtml "Python 模塊索引") | - [下一頁](toplevel_components.xhtml "9. 最高層級組件") | - [上一頁](simple_stmts.xhtml "7. 簡單語句") | - ![](https://box.kancloud.cn/a721fc7ec672275e257bbbfde49a4d4e_16x16.png) - [Python](https://www.python.org/) ? - zh\_CN 3.7.3 [文檔](../index.xhtml) ? - [Python 語言參考](index.xhtml) ? - $('.inline-search').show(0); | # 8. 復合語句 復合語句是包含其它語句(語句組)的語句;它們會以某種方式影響或控制所包含其它語句的執行。 通常,復合語句會跨越多行,雖然在某些簡單形式下整個復合語句也可能包含于一行之內。 [`if`](#if), [`while`](#while) 和 [`for`](#for) 語句用來實現傳統的控制流程構造。 [`try`](#try) 語句為一組語句指定異常處理和/和清理代碼,而 [`with`](#with) 語句允許在一個代碼塊周圍執行初始化和終結化代碼。 函數和類定義在語法上也屬于復合語句。 一條復合語句由一個或多個‘子句’組成。 一個子句則包含一個句頭和一個‘句體’。 特定復合語句的子句頭都處于相同的縮進層級。 每個子句頭以一個作為唯一標識的關鍵字開始并以一個冒號結束。 子句體是由一個子句控制的一組語句。 子句體可以是在子句頭的冒號之后與其同處一行的一條或由分號分隔的多條簡單語句,或者也可以是在其之后縮進的一行或多行語句。 只有后一種形式的子句體才能包含嵌套的復合語句;以下形式是不合法的,這主要是因為無法分清某個后續的 [`else`](#else) 子句應該屬于哪個 [`if`](#if) 子句: ``` if test1: if test2: print(x) ``` 還要注意的是在這種情形下分號的綁定比冒號更緊密,因此在以下示例中,所有 [`print()`](../library/functions.xhtml#print "print") 調用或者都不執行,或者都執行: ``` if x < y < z: print(x); print(y); print(z) ``` 總結: ``` compound_stmt ::= if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | async_with_stmt | async_for_stmt | async_funcdef suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT statement ::= stmt_list NEWLINE | compound_stmt stmt_list ::= simple_stmt (";" simple_stmt)* [";"] ``` 請注意語句總是以 `NEWLINE` 結束,之后可能跟隨一個 `DEDENT`。 還要注意可選的后續子句總是以一個不能作為語句開頭的關鍵字作為開頭,因此不會產生歧義(‘懸空的 [`else`](#else)’問題在 Python 中是通過要求嵌套的 [`if`](#if) 語句必須縮進來解決的)。 為了保證清晰,以下各節中語法規則采用將每個子句都放在單獨行中的格式。 ## 8.1. `if` 語句 [`if`](#if) 語句用于有條件的執行: ``` if_stmt ::= "if" expression ":" suite ("elif" expression ":" suite)* ["else" ":" suite] ``` 它通過對表達式逐個求值直至找到一個真值(請參閱 [布爾運算](expressions.xhtml#booleans) 了解真值與假值的定義)在子句體中選擇唯一匹配的一個;然后執行該子句體(而且 [`if`](#if) 語句的其他部分不會被執行或求值)。 如果所有表達式均為假值,則如果 [`else`](#else) 子句體如果存在就會被執行。 ## 8.2. `while` 語句 [`while`](#while) 語句用于在表達式保持為真的情況下重復地執行: ``` while_stmt ::= "while" expression ":" suite ["else" ":" suite] ``` 這將重復地檢驗表達式,并且如果其值為真就執行第一個子句體;如果表達式值為假(這可能在第一次檢驗時就發生)則如果 `else` 子句體存在就會被執行并終止循環。 第一個子句體中的 [`break`](simple_stmts.xhtml#break) 語句在執行時將終止循環且不執行 `else` 子句體。 第一個子句體中的 [`continue`](simple_stmts.xhtml#continue) 語句在執行時將跳過子句體中的剩余部分并返回檢驗表達式。 ## 8.3. `for` 語句 [`for`](#for) 語句用于對序列(例如字符串、元組或列表)或其他可迭代對象中的元素進行迭代: ``` for_stmt ::= "for" target_list "in" expression_list ":" suite ["else" ":" suite] ``` 表達式列表會被求值一次;它應該產生一個可迭代對象。 系統將為 `expression_list` 的結果創建一個迭代器,然后將為迭代器所提供的每一項執行一次子句體,具體次序與迭代器的返回順序一致。 每一項會按標準賦值規則 (參見 [賦值語句](simple_stmts.xhtml#assignment)) 被依次賦值給目標列表,然后子句體將被執行。 當所有項被耗盡時 (這會在序列為空或迭代器引發 [`StopIteration`](../library/exceptions.xhtml#StopIteration "StopIteration") 異常時立刻發生),`else` 子句的子句體如果存在將會被執行,并終止循環。 第一個子句體中的 [`break`](simple_stmts.xhtml#break) 語句在執行時將終止循環且不執行 `else` 子句體。 第一個子句體中的 [`continue`](simple_stmts.xhtml#continue) 語句在執行時將跳過子句體中的剩余部分并轉往下一項繼續執行,或者在沒有下一項時轉往 `else` 子句執行。 The for-loop makes assignments to the variables(s) in the target list. This overwrites all previous assignments to those variables including those made in the suite of the for-loop: ``` for i in range(10): print(i) i = 5 # this will not affect the for-loop # because i will be overwritten with the next # index in the range ``` 目標列表中的名稱在循環結束時不會被刪除,但如果序列為空,則它們根本不會被循環所賦值。 提示:內置函數 [`range()`](../library/stdtypes.xhtml#range "range") 會返回一個可迭代的整數序列,適用于模擬 Pascal 中的 `for i := a to b do` 這種效果;例如 `list(range(3))` 會返回列表 `[0, 1, 2]`。 注解 當序列在循環中被修改時會有一個微妙的問題(這只可能發生于可變序列例如列表中)。 會有一個內部計數器被用來跟蹤下一個要使用的項,每次迭代都會使計數器遞增。 當計數器值達到序列長度時循環就會終止。 這意味著如果語句體從序列中刪除了當前(或之前)的一項,下一項就會被跳過(因為其標號將變成已被處理的當前項的標號)。 類似地,如果語句體在序列當前項的前面插入一個新項,當前項會在循環的下一輪中再次被處理。 這會導致麻煩的程序錯誤,避免此問題的辦法是對整個序列使用切片來創建一個臨時副本,例如 ``` for x in a[:]: if x < 0: a.remove(x) ``` ## 8.4. `try` 語句 [`try`](#try) 語句可為一組語句指定異常處理器和/或清理代碼: ``` try_stmt ::= try1_stmt | try2_stmt try1_stmt ::= "try" ":" suite ("except" [expression ["as" identifier]] ":" suite)+ ["else" ":" suite] ["finally" ":" suite] try2_stmt ::= "try" ":" suite "finally" ":" suite ``` [`except`](#except) 子句指定一個或多個異常處理器。 當 [`try`](#try) 子句中沒有發生異常時,沒有異常處理器會被執行。 當 `try` 子句中發生異常時,將啟動對異常處理器的搜索。 此搜索會依次檢查 except 子句,直至找到與該異常相匹配的子句。 如果存在無表達式的 except 子句,它必須是最后一個;它將匹配任何異常。 對于帶有表達式的 except 子句,該表達式會被求值,如果結果對象與發生的異常“兼容”則該子句將匹配該異常。 一個對象如果是異常對象所屬的類或基類,或者是包含有兼容該異常的項的元組則兩者就是兼容的。 如果沒有 except 子句與異常相匹配,則會在周邊代碼和發起調用棧上繼續搜索異常處理器。 [1](#id4) 如果在對 except 子句頭中的表達式求值時引發了異常,則原來對處理器的搜索會被取消,并在周邊代碼和調用棧上啟動對新異常的搜索(它會被視作是整個 [`try`](#try) 語句所引發的異常)。 當找到一個匹配的 except 子句時,該異常將被賦值給該 except 子句在 `as` 關鍵字之后指定的目標,如果存在此關鍵字的話,并且該 except 子句體將被執行。 所有 except 子句都必須有可執行的子句體。 當到達子句體的末尾時,通常會轉向整個 try 語句之后繼續執行。 (這意味著如果對于同一異常存在有嵌套的兩個處理器,而異常發生于內層處理器的 try 子句中,則外層處理器將不會處理該異常。) 當使用 `as` 將目標賦值為一個異常時,它將在 except 子句結束時被清除。 這就相當于 ``` except E as N: foo ``` 被轉寫為 ``` except E as N: try: foo finally: del N ``` 這意味著異常必須賦值給一個不同的名稱才能在 except 子句之后引用它。 異常會被清除是因為在附加了回溯信息的情況下,它們會形成堆棧幀的循環引用,使得所有局部變量保持存活直到發生下一次垃圾回收。 在一個 except 子句體被執行之前,有關異常的詳細信息存放在 [`sys`](../library/sys.xhtml#module-sys "sys: Access system-specific parameters and functions.") 模塊中,可通過 [`sys.exc_info()`](../library/sys.xhtml#sys.exc_info "sys.exc_info") 來訪問。 [`sys.exc_info()`](../library/sys.xhtml#sys.exc_info "sys.exc_info") 返回一個 3 元組,由異常類、異常實例和回溯對象組成(參見 [標準類型層級結構](datamodel.xhtml#types) 一節),用于在程序中標識異常發生點。 當從處理異常的函數返回時 [`sys.exc_info()`](../library/sys.xhtml#sys.exc_info "sys.exc_info") 的值會恢復為(調用前的)原值。 如果控制流離開 [`try`](#try) 子句體時沒有引發異常,并且沒有執行 [`return`](simple_stmts.xhtml#return), [`continue`](simple_stmts.xhtml#continue) 或 [`break`](simple_stmts.xhtml#break) 語句,可選的 `else` 子句將被執行。 `else` 語句中的異常不會由之前的 [`except`](#except) 子句處理。 如果存在 [`finally`](#finally),它將指定‘清理’處理器。 [`try`](#try) 子句會被執行,包括任何 [`except`](#except) 和 `else` 子句。 如果在這些子句中發生任何未處理的異常,該異常會被臨時保存。 `finally` 子句將被執行。 如果存在被保存的異常,它會在 `finally` 子句的末尾被重新引發。 如果 `finally` 子句引發了另一個異常,被保存的異常會被設為新異常的上下文。 如果 `finally` 子句執行了 [`return`](simple_stmts.xhtml#return) 或 [`break`](simple_stmts.xhtml#break) 語句,被保存的異常會被丟棄: ``` >>> def f(): ... try: ... 1/0 ... finally: ... return 42 ... >>> f() 42 ``` 在 [`finally`](#finally) 子句執行期間,程序不能獲取異常信息。 當 [`return`](simple_stmts.xhtml#return), [`break`](simple_stmts.xhtml#break) 或 [`continue`](simple_stmts.xhtml#continue) 語句在一個 `try`...`finally` 語句的 [`try`](#try) 子句體中被執行時,[`finally`](#finally) 子句也會‘在離開時’被執行。 [`continue`](simple_stmts.xhtml#continue) 語句在 `finally` 子句中是不合法的。 (原因在于當前實現存在一個問題 --- 此限制可能會在未來去除)。 函數的返回值是由最后被執行的 [`return`](simple_stmts.xhtml#return) 語句所決定的。 由于 [`finally`](#finally) 子句總是被執行,因此在 `finally` 子句中被執行的 `return` 語句總是最后被執行的: ``` >>> def foo(): ... try: ... return 'try' ... finally: ... return 'finally' ... >>> foo() 'finally' ``` 有關異常的更多信息可以在 [異常](executionmodel.xhtml#exceptions) 一節找到,有關使用 [`raise`](simple_stmts.xhtml#raise) 語句生成異常的信息可以在 [raise 語句](simple_stmts.xhtml#raise) 一節找到。 ## 8.5. `with` 語句 [`with`](#with) 語句用于包裝帶有使用上下文管理器 (參見 [with 語句上下文管理器](datamodel.xhtml#context-managers) 一節) 定義的方法的代碼塊的執行。 這允許對普通的 [`try`](#try)...[`except`](#except)...[`finally`](#finally) 使用模式進行封裝以方便地重用。 ``` with_stmt ::= "with" with_item ("," with_item)* ":" suite with_item ::= expression ["as" target] ``` 帶有一個“項目”的 [`with`](#with) 語句的執行過程如下: 1. 對上下文表達式 (在 [`with_item`](#grammar-token-with-item) 中給出的表達式) 求值以獲得一個上下文管理器。 2. 載入上下文管理器的 [`__exit__()`](datamodel.xhtml#object.__exit__ "object.__exit__") 以便后續使用。 3. 發起調用上下文管理器的 [`__enter__()`](datamodel.xhtml#object.__enter__ "object.__enter__") 方法。 4. 如果 [`with`](#with) 語句中包含一個目標,來自 [`__enter__()`](datamodel.xhtml#object.__enter__ "object.__enter__") 的返回值將被賦值給它。 注解 [`with`](#with) 語句會保證如果 [`__enter__()`](datamodel.xhtml#object.__enter__ "object.__enter__") 方法返回時未發生錯誤,則 [`__exit__()`](datamodel.xhtml#object.__exit__ "object.__exit__") 將總是被調用。 因此,如果在對目標列表賦值期間發生錯誤,則會將其視為在語句體內部發生的錯誤。 參見下面的第 6 步。 5. 執行語句體。 6. 發起調用上下文管理器的 [`__exit__()`](datamodel.xhtml#object.__exit__ "object.__exit__") 方法。 如果語句體的退出是由異常導致的,則其類型、值和回溯信息將被作為參數傳遞給 [`__exit__()`](datamodel.xhtml#object.__exit__ "object.__exit__")。 否則的話,將提供三個 [`None`](../library/constants.xhtml#None "None") 參數。 如果語句體的退出是由異常導致的,并且來自 [`__exit__()`](datamodel.xhtml#object.__exit__ "object.__exit__") 方法的返回值為假,則該異常會被重新引發。 如果返回值為真,則該異常會被抑制,并會繼續執行 [`with`](#with) 語句之后的語句。 如果語句體由于異常以外的任何原因退出,則來自 [`__exit__()`](datamodel.xhtml#object.__exit__ "object.__exit__") 的返回值會被忽略,并會在該類退出正常的發生位置繼續執行。 如果有多個項目,則會視作存在多個 [`with`](#with) 語句嵌套來處理多個上下文管理器: ``` with A() as a, B() as b: suite ``` 等價于 ``` with A() as a: with B() as b: suite ``` 在 3.1 版更改: 支持多個上下文表達式。 參見 [**PEP 343**](https://www.python.org/dev/peps/pep-0343) \[https://www.python.org/dev/peps/pep-0343\] - "with" 語句Python [`with`](#with) 語句的規范描述、背景和示例。 ## 8.6. 函數定義 函數定義就是對用戶自定義函數的定義(參見 [標準類型層級結構](datamodel.xhtml#types) 一節): ``` funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite decorators ::= decorator+ decorator ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE dotted_name ::= identifier ("." identifier)* parameter_list ::= defparameter ("," defparameter)* ["," [parameter_list_starargs]] | parameter_list_starargs parameter_list_starargs ::= "*" [parameter] ("," defparameter)* ["," ["**" parameter [","]]] | "**" parameter [","] parameter ::= identifier [":" expression] defparameter ::= parameter ["=" expression] funcname ::= identifier ``` 函數定義是一條可執行語句。 它執行時會在當前局部命名空間中將函數名稱綁定到一個函數對象(函數可執行代碼的包裝器)。 這個函數對象包含對當前全局命名空間的引用,作為函數被調用時所使用的全局命名空間。 函數定義并不會執行函數體;只有當函數被調用時才會執行此操作。 [2](#id5) 一個函數定義可以被一個或多個 [decorator](../glossary.xhtml#term-decorator) 表達式所包裝。 當函數被定義時將在包含該函數定義的作用域中對裝飾器表達式求值。 求值結果必須是一個可調用對象,它會以該函數對象作為唯一參數被發起調用。 其返回值將被綁定到函數名稱而非函數對象。 多個裝飾器會以嵌套方式被應用。 例如以下代碼 ``` @f1(arg) @f2 def func(): pass ``` 大致等價于 ``` def func(): pass func = f1(arg)(f2(func)) ``` 不同之處在于原始函數并不會被臨時綁定到名稱 `func`。 當一個或多個 [形參](../glossary.xhtml#term-parameter) 具有 *形參*`=` *表達式* 這樣的形式時,該函數就被稱為具有“默認形參值”。 對于一個具有默認值的形參,其對應的 [argument](../glossary.xhtml#term-argument) 可以在調用中被省略,在此情況下會用形參的默認值來替代。 如果一個形參具有默認值,后續所有在 "`*`" 之前的形參也必須具有默認值 --- 這個句法限制并未在語法中明確表達。 **默認形參值會在執行函數定義時按從左至右的順序被求值。** 這意味著當函數被定義時將對表達式求值一次,相同的“預計算”值將在每次調用時被使用。 這一點在默認形參為可變對象,例如列表或字典的時候尤其需要重點理解:如果函數修改了該對象(例如向列表添加了一項),則實際上默認值也會被修改。 這通常不是人們所預期的。 繞過此問題的一個方法是使用 `None` 作為默認值,并在函數體中顯式地對其進行測試,例如: ``` def whats_on_the_telly(penguin=None): if penguin is None: penguin = [] penguin.append("property of the zoo") return penguin ``` 函數調用的語義在 [調用](expressions.xhtml#calls) 一節中有更詳細的描述。 函數調用總是會給形參列表中列出的所有形參賦值,或用位置參數,或用關鍵字參數,或用默認值。 如果存在 "`*identifier`" 這樣的形式,它會被初始化為一個元組來接收任何額外的位置參數,默認為空元組。 如果存在 "`**identifier`" 這樣的形式,它會被初始化為一個新的有序映射來接收任何額外的關鍵字參數,默認為一個相同類型的空映射。 在 "`*`" 或 "`*identifier`" 之后的形參都是僅關鍵字形參,只能通過關鍵字參數傳入值。 形參可以帶有 [標注](../glossary.xhtml#term-function-annotation),其形式為在形參名稱后加上 "`: expression`"。 任何形參都可以帶有標注,甚至 `*identifier` 或 `**identifier` 這樣的形參也可以。 函數可以帶有“返回”標注,其形式為在形參列表后加上 "`-> expression`"。 這些標注可以是任何有效的 Python 表達式。 標注的存在不會改變函數的語義。 標注值可以作為函數對象的 `__annotations__` 屬性中以對應形參名稱為鍵的字典值被訪問。 如果使用了 `annotations` import from [`__future__`](../library/__future__.xhtml#module-__future__ "__future__: Future statement definitions") 的方式,則標注會在運行時保存為字符串以啟用延遲求值特性。 否則,它們會在執行函數定義時被求值。 在這種情況下,標注的求值順序可能與它們在源代碼中出現的順序不同。 創建匿名函數(未綁定到一個名稱的函數)以便立即在表達式中使用也是可能的。 這需要使用 lambda 表達式,具體描述見 [lambda 表達式](expressions.xhtml#lambda) 一節。 請注意 lambda 只是簡單函數定義的一種簡化寫法;在 "[`def`](#def)" 語句中定義的函數也可以像用 lambda 表達式定義的函數一樣被傳遞或賦值給其他名稱。 "`def`" 形式實際上更為強大,因為它允許執行多條語句和使用標注。 **程序員注意事項:** 函數屬于一類對象。 在一個函數內部執行的 "`def`" 語句會定義一個局部函數并可被返回或傳遞。 在嵌套函數中使用的自由變量可以訪問包含該 def 語句的函數的局部變量。 詳情參見 [命名與綁定](executionmodel.xhtml#naming) 一節。 參見 [**PEP 3107**](https://www.python.org/dev/peps/pep-3107) \[https://www.python.org/dev/peps/pep-3107\] - 函數標注最初的函數標注規范說明。 [**PEP 484**](https://www.python.org/dev/peps/pep-0484) \[https://www.python.org/dev/peps/pep-0484\] - 類型提示標注的標準含意定義:類型提示。 [**PEP 526**](https://www.python.org/dev/peps/pep-0526) \[https://www.python.org/dev/peps/pep-0526\] - 變量標注的語法變量聲明的類型提示功能,包括類變量和實例變量 [**PEP 563**](https://www.python.org/dev/peps/pep-0563) \[https://www.python.org/dev/peps/pep-0563\] - 延遲的標注求值支持在運行時通過以字符串形式保存標注而非不是即求值來實現標注內部的向前引用。 ## 8.7. 類定義 類定義就是對類對象的定義 (參見 [標準類型層級結構](datamodel.xhtml#types) 一節): ``` classdef ::= [decorators] "class" classname [inheritance] ":" suite inheritance ::= "(" [argument_list] ")" classname ::= identifier ``` 類定義是一條可執行語句。 其中繼承列表通常給出基類的列表 (進階用法請參見 [元類](datamodel.xhtml#metaclasses)),列表中的每一項都應當被求值為一個允許子類的類對象。 沒有繼承列表的類默認繼承自基類 [`object`](../library/functions.xhtml#object "object");因此,: ``` class Foo: pass ``` 等價于 ``` class Foo(object): pass ``` 隨后類體將在一個新的執行幀 (參見 [命名與綁定](executionmodel.xhtml#naming)) 中被執行,使用新創建的局部命名空間和原有的全局命名空間。 (通常,類體主要包含函數定義。) 當類體結束執行時,其執行幀將被丟棄而其局部命名空間會被保存。 [3](#id6) 一個類對象隨后會被創建,其基類使用給定的繼承列表,屬性字典使用保存的局部命名空間。 類名稱將在原有的全局命名空間中綁定到該類對象。 在類體內定義的屬性的順序保存在新類的 `__dict__` 中。 請注意此順序的可靠性只限于類剛被創建時,并且只適用于使用定義語法所定義的類。 類的創建可使用 [元類](datamodel.xhtml#metaclasses) 進行重度定制。 類也可以被裝飾:就像裝飾函數一樣,: ``` @f1(arg) @f2 class Foo: pass ``` 大致等價于 ``` class Foo: pass Foo = f1(arg)(f2(Foo)) ``` 裝飾器表達式的求值規則與函數裝飾器相同。 結果隨后會被綁定到類名稱。 **程序員注意事項:** 在類定義內定義的變量是類屬性;它們將被類實例所共享。 實例屬性可通過 `self.name = value` 在方法中設定。 類和實例屬性均可通過 "`self.name`" 表示法來訪問,當通過此方式訪問時實例屬性會隱藏同名的類屬性。 類屬性可被用作實例屬性的默認值,但在此場景下使用可變值可能導致未預期的結果。 可以使用 [描述器](datamodel.xhtml#descriptors) 來創建具有不同實現細節的實例變量。 參見 [**PEP 3115**](https://www.python.org/dev/peps/pep-3115) \[https://www.python.org/dev/peps/pep-3115\] - Python 3000 中的元類將元類聲明修改為當前語法的提議,以及關于如何構建帶有元類的類的語義描述。 [**PEP 3129**](https://www.python.org/dev/peps/pep-3129) \[https://www.python.org/dev/peps/pep-3129\] - 類裝飾器增加類裝飾器的提議。 函數和方法裝飾器是在 [**PEP 318**](https://www.python.org/dev/peps/pep-0318) \[https://www.python.org/dev/peps/pep-0318\] 中被引入的。 ## 8.8. 協程 3\.5 新版功能. ### 8.8.1. 協程函數定義 ``` async_funcdef ::= [decorators] "async" "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite ``` Python 協程可以在多個位置上掛起和恢復執行 (參見 [coroutine](../glossary.xhtml#term-coroutine))。 在協程函數體內部,`await` 和 `async` 標識符已成為保留關鍵字;[`await`](expressions.xhtml#await) 表達式,[`async for`](#async-for) 以及 [`async with`](#async-with) 只能在協程函數體中使用。 使用 `async def` 語法定義的函數總是為協程函數,即使它們不包含 `await` 或 `async` 關鍵字。 在協程函數體中使用 `yield from` 表達式將引發 [`SyntaxError`](../library/exceptions.xhtml#SyntaxError "SyntaxError")。 協程函數的例子: ``` async def func(param1, param2): do_stuff() await some_coroutine() ``` ### 8.8.2. `async for` 語句 ``` async_for_stmt ::= "async" for_stmt ``` [asynchronous iterable](../glossary.xhtml#term-asynchronous-iterable) 能夠在其 *iter* 實現中調用異步代碼,而 [asynchronous iterator](../glossary.xhtml#term-asynchronous-iterator) 可以在其 *next* 方法中調用異步代碼。 `async for` 語句允許方便地對異步迭代器進行迭代。 以下代碼: ``` async for TARGET in ITER: BLOCK else: BLOCK2 ``` 在語義上等價于: ``` iter = (ITER) iter = type(iter).__aiter__(iter) running = True while running: try: TARGET = await type(iter).__anext__(iter) except StopAsyncIteration: running = False else: BLOCK else: BLOCK2 ``` 另請參閱 [`__aiter__()`](datamodel.xhtml#object.__aiter__ "object.__aiter__") 和 [`__anext__()`](datamodel.xhtml#object.__anext__ "object.__anext__") 了解詳情。 在協程函數體之外使用 `async for` 語句將引發 [`SyntaxError`](../library/exceptions.xhtml#SyntaxError "SyntaxError")。 ### 8.8.3. `async with` 語句 ``` async_with_stmt ::= "async" with_stmt ``` [asynchronous context manager](../glossary.xhtml#term-asynchronous-context-manager) 是一種 [context manager](../glossary.xhtml#term-context-manager),能夠在其 *enter* 和 *exit* 方法中暫停執行。 以下代碼: ``` async with EXPR as VAR: BLOCK ``` 在語義上等價于: ``` mgr = (EXPR) aexit = type(mgr).__aexit__ aenter = type(mgr).__aenter__(mgr) VAR = await aenter try: BLOCK except: if not await aexit(mgr, *sys.exc_info()): raise else: await aexit(mgr, None, None, None) ``` 另請參閱 [`__aenter__()`](datamodel.xhtml#object.__aenter__ "object.__aenter__") 和 [`__aexit__()`](datamodel.xhtml#object.__aexit__ "object.__aexit__") 了解詳情。 在協程函數體之外使用 `async with` 語句將引發 [`SyntaxError`](../library/exceptions.xhtml#SyntaxError "SyntaxError")。 參見 [**PEP 492**](https://www.python.org/dev/peps/pep-0492) \[https://www.python.org/dev/peps/pep-0492\] - 使用 async 和 await 語法實現協程將協程作為 Python 中的一個正式的單獨概念,并增加相應的支持語法。 腳注 [1](#id1)異常會被傳播給發起調用棧,除非存在一個 [`finally`](#finally) 子句正好引發了另一個異常。 新引發的異常將導致舊異常的丟失。 [2](#id2)作為函數體的第一條語句出現的字符串字面值會被轉換為函數的 `__doc__` 屬性,也就是該函數的 [docstring](../glossary.xhtml#term-docstring)。 [3](#id3)作為類體的第一條語句出現的字符串字面值會被轉換為命名空間的 `__doc__` 條目,也就是該類的 [docstring](../glossary.xhtml#term-docstring)。 ### 導航 - [索引](../genindex.xhtml "總目錄") - [模塊](../py-modindex.xhtml "Python 模塊索引") | - [下一頁](toplevel_components.xhtml "9. 最高層級組件") | - [上一頁](simple_stmts.xhtml "7. 簡單語句") | - ![](https://box.kancloud.cn/a721fc7ec672275e257bbbfde49a4d4e_16x16.png) - [Python](https://www.python.org/) ? - zh\_CN 3.7.3 [文檔](../index.xhtml) ? - [Python 語言參考](index.xhtml) ? - $('.inline-search').show(0); | ? [版權所有](../copyright.xhtml) 2001-2019, Python Software Foundation. Python 軟件基金會是一個非盈利組織。 [請捐助。](https://www.python.org/psf/donations/) 最后更新于 5月 21, 2019. [發現了問題](../bugs.xhtml)? 使用[Sphinx](http://sphinx.pocoo.org/)1.8.4 創建。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看