掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
復(fù)合語句是包含其它語句(語句組)的語句;它們會(huì)以某種方式影響或控制所包含其它語句的執(zhí)行。 通常,復(fù)合語句會(huì)跨越多行,雖然在某些簡單形式下整個(gè)復(fù)合語句也可能包含于一行之內(nèi)。

在浪卡子等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站建設(shè)、網(wǎng)站制作 網(wǎng)站設(shè)計(jì)制作定制網(wǎng)站制作,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),全網(wǎng)整合營銷推廣,外貿(mào)網(wǎng)站建設(shè),浪卡子網(wǎng)站建設(shè)費(fèi)用合理。
if, while 和 for 語句用來實(shí)現(xiàn)傳統(tǒng)的控制流程構(gòu)造。 try 語句為一組語句指定異常處理和/和清理代碼,而 with 語句允許在一個(gè)代碼塊周圍執(zhí)行初始化和終結(jié)化代碼。 函數(shù)和類定義在語法上也屬于復(fù)合語句。
一條復(fù)合語句由一個(gè)或多個(gè)‘子句’組成。 一個(gè)子句則包含一個(gè)句頭和一個(gè)‘句體’。 特定復(fù)合語句的子句頭都處于相同的縮進(jìn)層級(jí)。 每個(gè)子句頭以一個(gè)作為唯一標(biāo)識(shí)的關(guān)鍵字開始并以一個(gè)冒號(hào)結(jié)束。 子句體是由一個(gè)子句控制的一組語句。 子句體可以是在子句頭的冒號(hào)之后與其同處一行的一條或由分號(hào)分隔的多條簡單語句,或者也可以是在其之后縮進(jìn)的一行或多行語句。 只有后一種形式的子句體才能包含嵌套的復(fù)合語句;以下形式是不合法的,這主要是因?yàn)闊o法分清某個(gè)后續(xù)的 else 子句應(yīng)該屬于哪個(gè) if 子句:
if test1: if test2: print(x)
還要注意的是在這種情形下分號(hào)的綁定比冒號(hào)更緊密,因此在以下示例中,所有 print() 調(diào)用或者都不執(zhí)行,或者都執(zhí)行:
if x < y < z: print(x); print(y); print(z)
總結(jié):
- compound_stmt ::= if_stmt
- | while_stmt
- | for_stmt
- | try_stmt
- | with_stmt
- | match_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)* [";"]
請(qǐng)注意語句總是以 NEWLINE 結(jié)束,之后可能跟隨一個(gè) DEDENT。 還要注意可選的后續(xù)子句總是以一個(gè)不能作為語句開頭的關(guān)鍵字作為開頭,因此不會(huì)產(chǎn)生歧義(‘懸空的 else’問題在 python 中是通過要求嵌套的 if 語句必須縮進(jìn)來解決的)。
為了保證清晰,以下各節(jié)中語法規(guī)則采用將每個(gè)子句都放在單獨(dú)行中的格式。
if 語句if 語句用于有條件的執(zhí)行:
- if_stmt ::= "if" assignment_expression ":" suite
- ("elif" assignment_expression ":" suite)*
- ["else" ":" suite]
它通過對(duì)表達(dá)式逐個(gè)求值直至找到一個(gè)真值(請(qǐng)參閱 布爾運(yùn)算 了解真值與假值的定義)在子句體中選擇唯一匹配的一個(gè);然后執(zhí)行該子句體(而且 if 語句的其他部分不會(huì)被執(zhí)行或求值)。 如果所有表達(dá)式均為假值,則如果 else 子句體如果存在就會(huì)被執(zhí)行。
while 語句while 語句用于在表達(dá)式保持為真的情況下重復(fù)地執(zhí)行:
- while_stmt ::= "while" assignment_expression ":" suite
- ["else" ":" suite]
這將重復(fù)地檢驗(yàn)表達(dá)式,并且如果其值為真就執(zhí)行第一個(gè)子句體;如果表達(dá)式值為假(這可能在第一次檢驗(yàn)時(shí)就發(fā)生)則如果 else 子句體存在就會(huì)被執(zhí)行并終止循環(huán)。
第一個(gè)子句體中的 break 語句在執(zhí)行時(shí)將終止循環(huán)且不執(zhí)行 else 子句體。 第一個(gè)子句體中的 continue 語句在執(zhí)行時(shí)將跳過子句體中的剩余部分并返回檢驗(yàn)表達(dá)式。
for 語句for 語句用于對(duì)序列(例如字符串、元組或列表)或其他可迭代對(duì)象中的元素進(jìn)行迭代:
- for_stmt ::= "for" target_list "in" starred_list ":" suite
- ["else" ":" suite]
The starred_list expression is evaluated once; it should yield an iterable object. An iterator is created for that iterable. The first item provided by the iterator is then assigned to the target list using the standard rules for assignments (see 賦值語句), and the suite is executed. This repeats for each item provided by the iterator. When the iterator is exhausted, the suite in the else clause, if present, is executed, and the loop terminates.
第一個(gè)子句體中的 break 語句在執(zhí)行時(shí)將終止循環(huán)且不執(zhí)行 else 子句體。 第一個(gè)子句體中的 continue 語句在執(zhí)行時(shí)將跳過子句體中的剩余部分并轉(zhuǎn)往下一項(xiàng)繼續(xù)執(zhí)行,或者在沒有下一項(xiàng)時(shí)轉(zhuǎn)往 else 子句執(zhí)行。
for 循環(huán)會(huì)對(duì)目標(biāo)列表中的變量進(jìn)行賦值。 這將覆蓋之前對(duì)這些變量的所有賦值,包括在 for 循環(huán)體中的賦值:
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
目標(biāo)列表中的名稱在循環(huán)結(jié)束時(shí)不會(huì)被刪除,但如果序列為空,則它們根本不會(huì)被循環(huán)所賦值。 提示:內(nèi)置函數(shù) range() 會(huì)返回一個(gè)可迭代的整數(shù)序列,適用于模擬 Pascal 中的 for i := a to b do 這種效果;例如 list(range(3)) 會(huì)返回列表 [0, 1, 2]。
在 3.11 版更改: Starred elements are now allowed in the expression list.
try 語句The try statement specifies exception handlers and/or cleanup code for a group of statements:
- try_stmt ::= try1_stmt | try2_stmt | try3_stmt
- try1_stmt ::= "try" ":" suite
- ("except" [expression ["as" identifier]] ":" suite)+
- ["else" ":" suite]
- ["finally" ":" suite]
- try2_stmt ::= "try" ":" suite
- ("except" "*" expression ["as" identifier] ":" suite)+
- ["else" ":" suite]
- ["finally" ":" suite]
- try3_stmt ::= "try" ":" suite
- "finally" ":" suite
有關(guān)異常的更多信息可以在 異常 一節(jié)找到,有關(guān)使用 raise 語句生成異常的信息可以在 raise 語句 一節(jié)找到。
except clauseThe except clause(s) specify one or more exception handlers. When no exception occurs in the try clause, no exception handler is executed. When an exception occurs in the try suite, a search for an exception handler is started. This search inspects the except clauses in turn until one is found that matches the exception. An expression-less except clause, if present, must be last; it matches any exception. For an except clause with an expression, that expression is evaluated, and the clause matches the exception if the resulting object is “compatible” with the exception. An object is compatible with an exception if the object is the class or a non-virtual base class of the exception object, or a tuple containing an item that is the class or a non-virtual base class of the exception object.
If no except clause matches the exception, the search for an exception handler continues in the surrounding code and on the invocation stack. 1
If the evaluation of an expression in the header of an except clause raises an exception, the original search for a handler is canceled and a search starts for the new exception in the surrounding code and on the call stack (it is treated as if the entire try statement raised the exception).
When a matching except clause is found, the exception is assigned to the target specified after the as keyword in that except clause, if present, and the except clause’s suite is executed. All except clauses must have an executable block. When the end of this block is reached, execution continues normally after the entire try statement. (This means that if two nested handlers exist for the same exception, and the exception occurs in the try clause of the inner handler, the outer handler will not handle the exception.)
When an exception has been assigned using as target, it is cleared at the end of the except clause. This is as if
except E as N:foo
被轉(zhuǎn)寫為
except E as N:try:foofinally:del N
This means the exception must be assigned to a different name to be able to refer to it after the except clause. Exceptions are cleared because with the traceback attached to them, they form a reference cycle with the stack frame, keeping all locals in that frame alive until the next garbage collection occurs.
Before an except clause’s suite is executed, details about the exception are stored in the sys module and can be accessed via sys.exc_info(). sys.exc_info() returns a 3-tuple consisting of the exception class, the exception instance and a traceback object (see section 標(biāo)準(zhǔn)類型層級(jí)結(jié)構(gòu)) identifying the point in the program where the exception occurred. The details about the exception accessed via sys.exc_info() are restored to their previous values when leaving an exception handler:
>>> print(sys.exc_info())(None, None, None)>>> try:... raise TypeError... except:... print(sys.exc_info())... try:... raise ValueError... except:... print(sys.exc_info())... print(sys.exc_info())...(, TypeError(), ) (, ValueError(), ) (, TypeError(), ) >>> print(sys.exc_info())(None, None, None)
except* clauseThe except* clause(s) are used for handling ExceptionGroups. The exception type for matching is interpreted as in the case of except, but in the case of exception groups we can have partial matches when the type matches some of the exceptions in the group. This means that multiple except* clauses can execute, each handling part of the exception group. Each clause executes at most once and handles an exception group of all matching exceptions. Each exception in the group is handled by at most one except* clause, the first that matches it.
>>> try:... raise ExceptionGroup("eg",... [ValueError(1), TypeError(2), OSError(3), OSError(4)])... except* TypeError as e:... print(f'caught {type(e)} with nested {e.exceptions}')... except* OSError as e:... print(f'caught {type(e)} with nested {e.exceptions}')...caughtwith nested (TypeError(2),) caughtwith nested (OSError(3), OSError(4)) + Exception Group Traceback (most recent call last):| File "", line 2, in | ExceptionGroup: eg+-+---------------- 1 ----------------| ValueError: 1+------------------------------------
Any remaining exceptions that were not handled by any except* clause are re-raised at the end, combined into an exception group along with all exceptions that were raised from within except* clauses.
If the raised exception is not an exception group and its type matches one of the except* clauses, it is caught and wrapped by an exception group with an empty message string.
>>> try:... raise BlockingIOError... except* BlockingIOError as e:... print(repr(e))...ExceptionGroup('', (BlockingIOError()))
An except* clause must have a matching type, and this type cannot be a subclass of BaseExceptionGroup. It is not possible to mix except and except* in the same try. break, continue and return cannot appear in an except* clause.
else clause如果控制流離開 try 子句體時(shí)沒有引發(fā)異常,并且沒有執(zhí)行 return, continue 或 break 語句,可選的 else 子句將被執(zhí)行。 else 語句中的異常不會(huì)由之前的 except 子句處理。
finally clauseIf finally is present, it specifies a ‘cleanup’ handler. The try clause is executed, including any except and else clauses. If an exception occurs in any of the clauses and is not handled, the exception is temporarily saved. The finally clause is executed. If there is a saved exception it is re-raised at the end of the finally clause. If the finally clause raises another exception, the saved exception is set as the context of the new exception. If the finally clause executes a return, break or continue statement, the saved exception is discarded:
>>> def f():... try:... 1/0... finally:... return 42...>>> f()42
The exception information is not available to the program during execution of the finally clause.
When a return, break or continue statement is executed in the try suite of a try…finally statement, the finally clause is also executed ‘on the way out.’
The return value of a function is determined by the last return statement executed. Since the finally clause always executes, a return statement executed in the finally clause will always be the last one executed:
>>> def foo():... try:... return 'try'... finally:... return 'finally'...>>> foo()'finally'
在 3.8 版更改: Prior to Python 3.8, a continue statement was illegal in the finally clause due to a problem with the implementation.
with 語句with 語句用于包裝帶有使用上下文管理器 (參見 with 語句上下文管理器 一節(jié)) 定義的方法的代碼塊的執(zhí)行。 這允許對(duì)普通的 try…except…finally 使用模式進(jìn)行封裝以方便地重用。
- with_stmt ::= "with" ( "(" with_stmt_contents ","? ")" | with_stmt_contents ) ":" suite
- with_stmt_contents ::= with_item ("," with_item)*
- with_item ::= expression ["as" target]
帶有一個(gè)“項(xiàng)目”的 with 語句的執(zhí)行過程如下:
對(duì)上下文表達(dá)式(在 with_item 中給出的表達(dá)式)進(jìn)行求值來獲得上下文管理器。
載入上下文管理器的 __enter__() 以便后續(xù)使用。
載入上下文管理器的 __exit__() 以便后續(xù)使用。
發(fā)起調(diào)用上下文管理器的 __enter__() 方法。
如果 with 語句中包含一個(gè)目標(biāo),來自 __enter__() 的返回值將被賦值給它。
備注
with 語句會(huì)保證如果 __enter__() 方法返回時(shí)未發(fā)生錯(cuò)誤,則 __exit__() 將總是被調(diào)用。 因此,如果在對(duì)目標(biāo)列表賦值期間發(fā)生錯(cuò)誤,則會(huì)將其視為在語句體內(nèi)部發(fā)生的錯(cuò)誤。 參見下面的第 6 步。
執(zhí)行語句體。
發(fā)起調(diào)用上下文管理器的 __exit__() 方法。 如果語句體的退出是由異常導(dǎo)致的,則其類型、值和回溯信息將被作為參數(shù)傳遞給 __exit__()。 否則的話,將提供三個(gè) None 參數(shù)。
如果語句體的退出是由異常導(dǎo)致的,并且來自 __exit__() 方法的返回值為假,則該異常會(huì)被重新引發(fā)。 如果返回值為真,則該異常會(huì)被抑制,并會(huì)繼續(xù)執(zhí)行 with 語句之后的語句。
如果語句體由于異常以外的任何原因退出,則來自 __exit__() 的返回值會(huì)被忽略,并會(huì)在該類退出正常的發(fā)生位置繼續(xù)執(zhí)行。
以下代碼:
with EXPRESSION as TARGET:SUITE
在語義上等價(jià)于:
manager = (EXPRESSION)enter = type(manager).__enter__exit = type(manager).__exit__value = enter(manager)hit_except = Falsetry:TARGET = valueSUITEexcept:hit_except = Trueif not exit(manager, *sys.exc_info()):raisefinally:if not hit_except:exit(manager, None, None, None)
如果有多個(gè)項(xiàng)目,則會(huì)視作存在多個(gè) with 語句嵌套來處理多個(gè)上下文管理器:
with A() as a, B() as b:SUITE
在語義上等價(jià)于:
with A() as a:with B() as b:SUITE
也可以用圓括號(hào)包圍的多行形式的多項(xiàng)目上下文管理器。例如:
with (A() as a,B() as b,):SUITE
在 3.1 版更改: 支持多個(gè)上下文表達(dá)式。
在 3.10 版更改: Support for using grouping parentheses to break the statement in multiple lines.
參見
PEP 343 - “with” 語句
Python with 語句的規(guī)范描述、背景和示例。
match 語句3.10 新版功能.
匹配語句用于進(jìn)行模式匹配。語法如下:
- match_stmt ::= 'match' subject_expr ":" NEWLINE INDENT case_block+ DEDENT
- subject_expr ::=
star_named_expression","star_named_expressions?- |
named_expression- case_block ::= 'case' patterns [guard] ":"
block
備注
本節(jié)使用單引號(hào)來表示 軟關(guān)鍵字。
模式匹配接受一個(gè)模式作為輸入(跟在 case 后),一個(gè)目標(biāo)值(跟在 match 后)。該模式(可能包含子模式)將與目標(biāo)值進(jìn)行匹配。輸出是:
匹配成功或失?。ㄒ脖环Q為模式成功或失?。?。
可能將匹配的值綁定到一個(gè)名字上。 這方面的先決條件將在下面進(jìn)一步討論。
關(guān)鍵字 match 和 case 是 soft keywords 。
參見
PEP 634 —— 結(jié)構(gòu)化模式匹配:規(guī)范
PEP 636 —— 結(jié)構(gòu)化模式匹配:教程
匹配語句邏輯流程的概述如下:
對(duì)目標(biāo)表達(dá)式 subject_expr 求值后將結(jié)果作為匹配用的目標(biāo)值。 如果目標(biāo)表達(dá)式包含逗號(hào),則使用 the standard rules 構(gòu)建一個(gè)元組。
目標(biāo)值將依次與 case_block 中的每個(gè)模式進(jìn)行匹配。匹配成功或失敗的具體規(guī)則在下面描述。匹配嘗試也可以與模式中的一些或所有的獨(dú)立名稱綁定。準(zhǔn)確的模式綁定規(guī)則因模式類型而異,具體規(guī)定見下文。成功的模式匹配過程中產(chǎn)生的名稱綁定將超越所執(zhí)行的塊的范圍,可以在匹配語句之后使用。
備注
在模式匹配失敗時(shí),一些子模式可能會(huì)成功。 不要依賴于失敗匹配進(jìn)行的綁定。 反過來說,不要認(rèn)為變量在匹配失敗后保持不變。 確切的行為取決于實(shí)現(xiàn),可能會(huì)有所不同。 這是一個(gè)有意的決定,允許不同的實(shí)現(xiàn)添加優(yōu)化。
如果該模式匹配成功,并且完成了對(duì)相應(yīng)的約束項(xiàng)(如果存在)的求值。在這種情況下,保證完成所有的名稱綁定。
如果約束項(xiàng)求值為真或缺失,執(zhí)行 case_block 中的 block 。
否則,將按照上述方法嘗試下一個(gè) case_block 。
如果沒有進(jìn)一步的 case 塊,匹配語句終止。
備注
用戶一般不應(yīng)依賴正在求值的模式。 根據(jù)不同的實(shí)現(xiàn)方式,解釋器可能會(huì)緩存數(shù)值或使用其他優(yōu)化方法來避免重復(fù)求值。
匹配語句示例:
>>> flag = False>>> match (100, 200):... case (100, 300): # Mismatch: 200 != 300... print('Case 1')... case (100, 200) if flag: # Successful match, but guard fails... print('Case 2')... case (100, y): # Matches and binds y to 200... print(f'Case 3, y: {y}')... case _: # Pattern not attempted... print('Case 4, I match anything!')...Case 3, y: 200
在這個(gè)示例中,if flag 是約束項(xiàng)。請(qǐng)閱讀下一節(jié)以了解更多相關(guān)內(nèi)容。
- guard ::= "if"
named_expression
guard (它是 case 的一部分) 必須成立才能讓 case 語句塊中的代碼被執(zhí)行。 它所采用的形式為: if 之后跟一個(gè)表達(dá)式。
擁有 guard 的 case 塊的邏輯流程如下:
檢查 case 塊中的模式是否匹配成功。如果該模式匹配失敗,則不對(duì) guard 進(jìn)行求值,檢查下一個(gè) case 塊。
如果該模式匹配成功,對(duì) guard 求值。
如果 guard 求值為真,則選用該 case 塊。
如果 guard 求值為假,則不選用該 case 塊。
如果在對(duì) guard 求值過程中引發(fā)了異常,則異常將被拋出。
允許約束項(xiàng)產(chǎn)生副作用,因?yàn)樗麄兪潜磉_(dá)式。約束項(xiàng)求值必須從第一個(gè) case 塊到最后一個(gè) case 塊依次逐個(gè)進(jìn)行,模式匹配失敗的 case 塊將被跳過。(也就是說,約束項(xiàng)求值必須按順序進(jìn)行。)一旦選用了一個(gè) case 塊,約束項(xiàng)求值必須由此終止。
必定匹配的 case 塊是能匹配所有情況的 case 塊。一個(gè)匹配語句最多可以有一個(gè)必定匹配的 case 塊,而且必須是最后一個(gè)。
如果一個(gè) case 塊沒有約束項(xiàng),并且其模式是必定匹配的,那么它就被認(rèn)為是必定匹配的。 如果我們可以僅從語法上證明一個(gè)模式總是能匹配成功,那么這個(gè)模式就被認(rèn)為是必定匹配的。 只有以下模式是必定匹配的:
左側(cè)模式是必定匹配的 AS 模式
包含至少一個(gè)必定匹配模式的 或模式
捕獲模式
通配符模式
括號(hào)內(nèi)的必定匹配模式
備注
本節(jié)使用了超出標(biāo)準(zhǔn) EBNF 的語法符號(hào)。
符號(hào) SEP.RULE+ 是 RULE (SEP RULE)* 的簡寫
符號(hào) !RULE 是前向否定斷言的簡寫
patterns 的頂層語法是:
- patterns ::= open_sequence_pattern | pattern
- pattern ::= as_pattern | or_pattern
- closed_pattern ::= | literal_pattern
- | capture_pattern
- | wildcard_pattern
- | value_pattern
- | group_pattern
- | sequence_pattern
- | mapping_pattern
- | class_pattern
下面的描述將包括一個(gè)“簡而言之”以描述模式的作用,便于說明問題(感謝 Raymond Hettinger 提供的一份文件,大部分的描述受其啟發(fā))。請(qǐng)注意,這些描述純粹是為了說明問題,可能不 反映底層的實(shí)現(xiàn)。此外,它們并沒有涵蓋所有有效的形式。
或模式是由豎杠 | 分隔的兩個(gè)或更多的模式。語法:
- or_pattern ::= "|".closed_pattern+
只有最后的子模式可以是 必定匹配的,且每個(gè)子模式必須綁定相同的名字集以避免歧義。
或模式將目標(biāo)值依次與其每個(gè)子模式嘗試匹配,直到有一個(gè)匹配成功,然后該或模式被視作匹配成功。 否則,如果沒有任何子模式匹配成功,則或模式匹配失敗。
簡而言之,P1 | P2 | ... 會(huì)首先嘗試匹配 P1 ,如果失敗將接著嘗試匹配 P2 ,如果出現(xiàn)成功的匹配則立即結(jié)束且模式匹配成功,否則模式匹配失敗。
AS 模式將關(guān)鍵字 as 左側(cè)的或模式與目標(biāo)值進(jìn)行匹配。語法:
- as_pattern ::= or_pattern "as" capture_pattern
如果或模式匹配失敗,AS 模式也匹配失敗。 否則,AS 模式將目標(biāo)與關(guān)鍵字 as 右邊的名字綁定且匹配陳成功。 capture_pattern 不能是 _ 。
簡而言之, P as NAME 將與 P 匹配,成功后將設(shè)置 NAME = 。
字面值模式對(duì)應(yīng) Python 中的大多數(shù) 字面值。 語法為:
- literal_pattern ::=
signed_number- |
signed_number"+" NUMBER- |
signed_number"-" NUMBER- |
strings- | "None"
- | "True"
- | "False"
- |
signed_number: NUMBER | "-" NUMBER
規(guī)則 strings 和標(biāo)記 NUMBER 是在 standard Python grammar 中定義的。支持三引號(hào)的字符串。不支持原始字符串和字節(jié)字符串。也不支持 格式字符串字面值 。
signed_number '+' NUMBER 和 signed_number '-' NUMBER 形式是用于表示 復(fù)數(shù);它們要求左邊是一個(gè)實(shí)數(shù)而右邊是一個(gè)虛數(shù)。 例如 3 + 4j。
簡而言之, LITERAL 只會(huì)在 時(shí)匹配成功。對(duì)于單例 None 、 True 和 False ,會(huì)使用 is 運(yùn)算符。
捕獲模式將目標(biāo)值與一個(gè)名稱綁定。語法:
capture_pattern ::= !'_' NAME
單獨(dú)的一個(gè)下劃線 _ 不是捕獲模式( !'_' 表達(dá)的就是這個(gè)含義)。 它會(huì)被當(dāng)作 wildcard_pattern 。
在給定的模式中,一個(gè)名字只能被綁定一次。例如 case x, x: ... 時(shí)無效的,但 case [x] | x: ... 是被允許的。
捕獲模式總是能匹配成功。綁定遵循 PEP 572 中賦值表達(dá)式運(yùn)算符設(shè)立的作用域規(guī)則;名字在最接近的包含函數(shù)作用域內(nèi)成為一個(gè)局部變量,除非有適用的 global 或 nonlocal 語句。
簡而言之, NAME 總是會(huì)匹配成功且將設(shè)置 NAME = 。
通配符模式總是會(huì)匹配成功(匹配任何內(nèi)容)并且不綁定任何名稱。語法:
wildcard_pattern ::= '_'
在且僅在任何模式中 _ 是一個(gè) 軟關(guān)鍵字。 通常情況下它是一個(gè)標(biāo)識(shí)符,即使是在 match 的目標(biāo)表達(dá)式、guard 和 case 代碼塊中也是如此。
簡而言之,_ 總是會(huì)匹配成功。
值模式代表 Python 中具有名稱的值。語法:
- value_pattern ::= attr
- attr ::= name_or_attr "." NAME
- name_or_attr ::= attr | NAME
模式中帶點(diǎn)的名稱會(huì)使用標(biāo)準(zhǔn)的 Python 名稱解析規(guī)則 來查找。 如果找到的值與目標(biāo)值比較結(jié)果相等則模式匹配成功(使用 == 相等運(yùn)算符)。
簡而言之, NAME1.NAME2 僅在 時(shí)匹配成功。
備注
如果相同的值在同一個(gè)匹配語句中出現(xiàn)多次,解釋器可能會(huì)緩存找到的第一個(gè)值并重新使用它,而不是重復(fù)查找。 這種緩存與特定匹配語句的執(zhí)行嚴(yán)格掛鉤。
組模式允許用戶在模式周圍添加括號(hào),以強(qiáng)調(diào)預(yù)期的分組。 除此之外,它沒有額外的語法。語法:
- group_pattern ::= "(" pattern ")"
簡單來說 (P) 具有與 P 相同的效果。
一個(gè)序列模式包含數(shù)個(gè)將與序列元素進(jìn)行匹配的子模式。其語法類似于列表或元組的解包。
- sequence_pattern ::= "[" [maybe_sequence_pattern] "]"
- | "(" [open_sequence_pattern] ")"
- open_sequence_pattern ::= maybe_star_pattern "," [maybe_sequence_pattern]
- maybe_sequence_pattern ::= ",".maybe_star_pattern+ ","?
- maybe_star_pattern ::= star_pattern | pattern
- star_pattern ::= "*" (capture_pattern | wildcard_pattern)
序列模式中使用圓括號(hào)或方括號(hào)沒有區(qū)別(例如 (...) 和 [...] )。
備注
用圓括號(hào)括起來且沒有跟隨逗號(hào)的單個(gè)模式 (例如 (3 | 4)) 是一個(gè) 分組模式。 而用方括號(hào)括起來的單個(gè)模式 (例如 [3 | 4]) 則仍是一個(gè)序列模式。
一個(gè)序列模式中最多可以有一個(gè)星號(hào)子模式。星號(hào)子模式可以出現(xiàn)在任何位置。如果沒有星號(hào)子模式,該序列模式是固定長度的序列模式;否則,其是一個(gè)可變長度的序列模式。
下面是將一個(gè)序列模式與一個(gè)目標(biāo)值相匹配的邏輯流程:
如果目標(biāo)值不是一個(gè)序列 2 ,該序列模式匹配失敗。
如果目標(biāo)值是 str 、 bytes 或 bytearray 的實(shí)例,則該序列模式匹配失敗。
隨后的步驟取決于序列模式是固定長度還是可變長度的。
如果序列模式是固定長度的:
如果目標(biāo)序列的長度與子模式的數(shù)量不相等,則該序列模式匹配失敗
序列模式中的子模式與目標(biāo)序列中的相應(yīng)項(xiàng)目從左到右進(jìn)行匹配。 一旦一個(gè)子模式匹配失敗,就停止匹配。 如果所有的子模式都成功地與它們的對(duì)應(yīng)項(xiàng)相匹配,那么該序列模式就匹配成功了。
否則,如果序列模式是變長的:
如果目標(biāo)序列的長度小于非星號(hào)子模式的數(shù)量,則該序列模式匹配失敗。
與固定長度的序列一樣,靠前的非星形子模式與其相應(yīng)的項(xiàng)目進(jìn)行匹配。
如果上一步成功,星號(hào)子模式與剩余的目標(biāo)項(xiàng)形成的列表相匹配,不包括星號(hào)子模式之后的非星號(hào)子模式所對(duì)應(yīng)的剩余項(xiàng)。
剩余的非星號(hào)子模式將與相應(yīng)的目標(biāo)項(xiàng)匹配,就像固定長度的序列一樣。
備注
目標(biāo)序列的長度可通過 len() (即通過 __len__() 協(xié)議) 獲得。 解釋器可能會(huì)以類似于 值模式 的方式緩存這個(gè)長度信息。
簡而言之, [P1, P2, P3, … , P 僅在滿足以下情況時(shí)匹配成功:
檢查 是一個(gè)序列
len(subject) ==
將 P1 與 進(jìn)行匹配(請(qǐng)注意此匹配可以綁定名稱)
將 P2 與 進(jìn)行匹配(請(qǐng)注意此匹配可以綁定名稱)
…… 剩余對(duì)應(yīng)的模式/元素也以此類推。
映射模式包含一個(gè)或多個(gè)鍵值模式。其語法類似于字典的構(gòu)造。語法:
- mapping_pattern ::= "{" [items_pattern] "}"
- items_pattern ::= ",".key_value_pattern+ ","?
- key_value_pattern ::= (literal_pattern | value_pattern) ":" pattern
- | double_star_pattern
- double_star_pattern ::= "**" capture_pattern
一個(gè)映射模式中最多可以有一個(gè)雙星號(hào)模式。雙星號(hào)模式必須是映射模式中的最后一個(gè)子模式。
映射模式中不允許出現(xiàn)重復(fù)的鍵。重復(fù)的字面值鍵會(huì)引發(fā) SyntaxError 。若是兩個(gè)鍵有相同的值將會(huì)在運(yùn)行時(shí)引發(fā) ValueError 。
以下是映射模式與目標(biāo)值匹配的邏輯流程:
如果目標(biāo)值不是一個(gè)映射 3,則映射模式匹配失敗。
若映射模式中給出的每個(gè)鍵都存在于目標(biāo)映射中,且每個(gè)鍵的模式都與目標(biāo)映射的相應(yīng)項(xiàng)匹配成功,則該映射模式匹配成功。
如果在映射模式中檢測到重復(fù)的鍵,該模式將被視作無效。對(duì)于重復(fù)的字面值,會(huì)引發(fā) SyntaxError ;對(duì)于相同值的命名鍵,會(huì)引發(fā) ValueError 。
備注
鍵值對(duì)使用映射目標(biāo)的 get() 方法的雙參數(shù)形式進(jìn)行匹配。匹配的鍵值對(duì)必須已經(jīng)存在于映射中,而不是通過 __missing__() 或 __getitem__() 即時(shí)創(chuàng)建。
簡而言之, {KEY1: P1, KEY2: P2, ... } 僅在滿足以下情況時(shí)匹配成功:
檢查 是映射
KEY1 in
P1 與 相匹配
…… 剩余對(duì)應(yīng)的鍵/模式對(duì)也以此類推。
類模式表示一個(gè)類以及它的位置參數(shù)和關(guān)鍵字參數(shù)(如果有的話)。語法:
- class_pattern ::= name_or_attr "(" [pattern_arguments ","?] ")"
- pattern_arguments ::= positional_patterns ["," keyword_patterns]
- | keyword_patterns
- positional_patterns ::= ",".pattern+
- keyword_patterns ::= ",".keyword_pattern+
- keyword_pattern ::= NAME "=" pattern
同一個(gè)關(guān)鍵詞不應(yīng)該在類模式中重復(fù)出現(xiàn)。
以下是類模式與目標(biāo)值匹配的邏輯流程:
如果 name_or_attr 不是內(nèi)置 type 的實(shí)例,引發(fā) TypeError 。
如果目標(biāo)值不是 name_or_attr 的實(shí)例(通過 isinstance() 測試),該類模式匹配失敗。
如果沒有模式參數(shù)存在,則該模式匹配成功。 否則,后面的步驟取決于是否有關(guān)鍵字或位置參數(shù)模式存在。
對(duì)于一些內(nèi)置的類型(將在后文詳述),接受一個(gè)位置子模式,它將與整個(gè)目標(biāo)值相匹配;對(duì)于這些類型,關(guān)鍵字模式也像其他類型一樣工作。
如果只存在關(guān)鍵詞模式,它們將被逐一處理,如下所示:
一. 該關(guān)鍵詞被視作主體的一個(gè)屬性進(jìn)行查找。
如果這引發(fā)了除 AttributeError 以外的異常,該異常會(huì)被拋出。
如果這引發(fā)了 AttributeError ,該類模式匹配失敗。
否則,與關(guān)鍵詞模式相關(guān)的子模式將與目標(biāo)的屬性值進(jìn)行匹配。 如果失敗,則類模式匹配失?。蝗绻晒?,則繼續(xù)對(duì)下一個(gè)關(guān)鍵詞進(jìn)行匹配。
二. 如果所有的關(guān)鍵詞模式匹配成功,該類模式匹配成功。
如果存在位置模式,在匹配前會(huì)用類 name_or_attr 的 __match_args__ 屬性將其轉(zhuǎn)換為關(guān)鍵詞模式。
一. 進(jìn)行與 getattr(cls, "__match_args__", ()) 等價(jià)的調(diào)用。
如果這引發(fā)一個(gè)異常,該異常將被拋出。
如果返回值不是一個(gè)元組,則轉(zhuǎn)換失敗且引發(fā) TypeError 。
若位置模式的數(shù)量超出
len(cls.__match_args__),將引發(fā) TypeError 。否則,位置模式
i會(huì)使用__match_args__[i]轉(zhuǎn)換為關(guān)鍵詞。__match_args__[i]必須是一個(gè)字符串;如果不是則引發(fā) TypeError 。如果有重復(fù)的關(guān)鍵詞,引發(fā) TypeError 。
參見
定制類模式匹配中的位置參數(shù)
二. 若所有的位置模式都被轉(zhuǎn)換為關(guān)鍵詞模式,
匹配的過程就像只有關(guān)鍵詞模式一樣。
對(duì)于以下內(nèi)置類型,位置子模式的處理是不同的:
bool
bytearray
bytes
dict
float
frozenset
int
list
set
str
tuple
These classes accept a single positional argument, and the pattern there is matched against the whole object rather than an attribute. For example int(0|1) matches the value 0, but not the value 0.0.
簡而言之, CLS(P1, attr=P2) 僅在滿足以下情況時(shí)匹配成功:
isinstance(
用 CLS.__match_args__ 將 P1 轉(zhuǎn)換為關(guān)鍵詞模式
對(duì)于每個(gè)關(guān)鍵詞參數(shù) attr=P2 :
hasattr(
將 P2 與 進(jìn)行匹配
…… 剩余對(duì)應(yīng)的關(guān)鍵字參數(shù)/模式對(duì)也以此類推。
參見
PEP 634 —— 結(jié)構(gòu)化模式匹配:規(guī)范
PEP 636 —— 結(jié)構(gòu)化模式匹配:教程
函數(shù)定義就是對(duì)用戶自定義函數(shù)的定義(參見 標(biāo)準(zhǔn)類型層級(jí)結(jié)構(gòu) 一節(jié)):
- funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")"
- ["->" expression] ":" suite
- decorators ::= decorator+
- decorator ::= "@" assignment_expression NEWLINE
- parameter_list ::= defparameter ("," defparameter)* "," "/" ["," [parameter_list_no_posonly]]
- | parameter_list_no_posonly
- parameter_list_no_posonly ::= defparameter ("," defparameter)* ["," [parameter_list_starargs]]
- | parameter_list_starargs
- parameter_list_starargs ::= "*" [parameter] ("," defparameter)* ["," ["**" parameter [","]]]
- | "**" parameter [","]
- parameter ::= identifier [":" expression]
- defparameter ::= parameter ["=" expression]
- funcname ::= identifier
函數(shù)定義是一條可執(zhí)行語句。 它執(zhí)行時(shí)會(huì)在當(dāng)前局部命名空間中將函數(shù)名稱綁定到一個(gè)函數(shù)對(duì)象(函數(shù)可執(zhí)行代碼的包裝器)。 這個(gè)函數(shù)對(duì)象包含對(duì)當(dāng)前全局命名空間的引用,作為函數(shù)被調(diào)用時(shí)所使用的全局命名空間。
函數(shù)定義并不會(huì)執(zhí)行函數(shù)體;只有當(dāng)函數(shù)被調(diào)用時(shí)才會(huì)執(zhí)行此操作。 4
一個(gè)函數(shù)定義可以被一
本文名稱:創(chuàng)新互聯(lián)Python教程:8.復(fù)合語句
文章出自:http://uogjgqi.cn/article/cccphgc.html

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流