日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
創(chuàng)新互聯(lián)Python教程:8.復合語句

8. 復合語句

復合語句是包含其它語句(語句組)的語句;它們會以某種方式影響或控制所包含其它語句的執(zhí)行。 通常,復合語句會跨越多行,雖然在某些簡單形式下整個復合語句也可能包含于一行之內(nèi)。

在浪卡子等地區(qū),都構建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務理念,為客戶提供網(wǎng)站建設、網(wǎng)站制作 網(wǎng)站設計制作定制網(wǎng)站制作,公司網(wǎng)站建設,企業(yè)網(wǎng)站建設,成都品牌網(wǎng)站建設,全網(wǎng)整合營銷推廣,外貿(mào)網(wǎng)站建設,浪卡子網(wǎng)站建設費用合理。

if, while 和 for 語句用來實現(xiàn)傳統(tǒng)的控制流程構造。 try 語句為一組語句指定異常處理和/和清理代碼,而 with 語句允許在一個代碼塊周圍執(zhí)行初始化和終結化代碼。 函數(shù)和類定義在語法上也屬于復合語句。

一條復合語句由一個或多個‘子句’組成。 一個子句則包含一個句頭和一個‘句體’。 特定復合語句的子句頭都處于相同的縮進層級。 每個子句頭以一個作為唯一標識的關鍵字開始并以一個冒號結束。 子句體是由一個子句控制的一組語句。 子句體可以是在子句頭的冒號之后與其同處一行的一條或由分號分隔的多條簡單語句,或者也可以是在其之后縮進的一行或多行語句。 只有后一種形式的子句體才能包含嵌套的復合語句;以下形式是不合法的,這主要是因為無法分清某個后續(xù)的 else 子句應該屬于哪個 if 子句:

 
 
 
 
  1. if test1: if test2: print(x)

還要注意的是在這種情形下分號的綁定比冒號更緊密,因此在以下示例中,所有 print() 調(diào)用或者都不執(zhí)行,或者都執(zhí)行:

 
 
 
 
  1. if x < y < z: print(x); print(y); print(z)

總結:

 
 
 
 
  1. compound_stmt ::= if_stmt
  2. | while_stmt
  3. | for_stmt
  4. | try_stmt
  5. | with_stmt
  6. | match_stmt
  7. | funcdef
  8. | classdef
  9. | async_with_stmt
  10. | async_for_stmt
  11. | async_funcdef
  12. suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT
  13. statement ::= stmt_list NEWLINE | compound_stmt
  14. stmt_list ::= simple_stmt (";" simple_stmt)* [";"]

請注意語句總是以 NEWLINE 結束,之后可能跟隨一個 DEDENT。 還要注意可選的后續(xù)子句總是以一個不能作為語句開頭的關鍵字作為開頭,因此不會產(chǎn)生歧義(‘懸空的 else’問題在 python 中是通過要求嵌套的 if 語句必須縮進來解決的)。

為了保證清晰,以下各節(jié)中語法規(guī)則采用將每個子句都放在單獨行中的格式。

8.1. if 語句

if 語句用于有條件的執(zhí)行:

 
 
 
 
  1. if_stmt ::= "if" assignment_expression ":" suite
  2. ("elif" assignment_expression ":" suite)*
  3. ["else" ":" suite]

它通過對表達式逐個求值直至找到一個真值(請參閱 布爾運算 了解真值與假值的定義)在子句體中選擇唯一匹配的一個;然后執(zhí)行該子句體(而且 if 語句的其他部分不會被執(zhí)行或求值)。 如果所有表達式均為假值,則如果 else 子句體如果存在就會被執(zhí)行。

8.2. while 語句

while 語句用于在表達式保持為真的情況下重復地執(zhí)行:

 
 
 
 
  1. while_stmt ::= "while" assignment_expression ":" suite
  2. ["else" ":" suite]

這將重復地檢驗表達式,并且如果其值為真就執(zhí)行第一個子句體;如果表達式值為假(這可能在第一次檢驗時就發(fā)生)則如果 else 子句體存在就會被執(zhí)行并終止循環(huán)。

第一個子句體中的 break 語句在執(zhí)行時將終止循環(huán)且不執(zhí)行 else 子句體。 第一個子句體中的 continue 語句在執(zhí)行時將跳過子句體中的剩余部分并返回檢驗表達式。

8.3. for 語句

for 語句用于對序列(例如字符串、元組或列表)或其他可迭代對象中的元素進行迭代:

 
 
 
 
  1. for_stmt ::= "for" target_list "in" starred_list ":" suite
  2. ["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.

第一個子句體中的 break 語句在執(zhí)行時將終止循環(huán)且不執(zhí)行 else 子句體。 第一個子句體中的 continue 語句在執(zhí)行時將跳過子句體中的剩余部分并轉往下一項繼續(xù)執(zhí)行,或者在沒有下一項時轉往 else 子句執(zhí)行。

for 循環(huán)會對目標列表中的變量進行賦值。 這將覆蓋之前對這些變量的所有賦值,包括在 for 循環(huán)體中的賦值:

 
 
 
 
  1. for i in range(10):
  2. print(i)
  3. i = 5 # this will not affect the for-loop
  4. # because i will be overwritten with the next
  5. # index in the range

目標列表中的名稱在循環(huán)結束時不會被刪除,但如果序列為空,則它們根本不會被循環(huán)所賦值。 提示:內(nèi)置函數(shù) range() 會返回一個可迭代的整數(shù)序列,適用于模擬 Pascal 中的 for i := a to b do 這種效果;例如 list(range(3)) 會返回列表 [0, 1, 2]。

在 3.11 版更改: Starred elements are now allowed in the expression list.

8.4. try 語句

The try statement specifies exception handlers and/or cleanup code for a group of statements:

 
 
 
 
  1. try_stmt ::= try1_stmt | try2_stmt | try3_stmt
  2. try1_stmt ::= "try" ":" suite
  3. ("except" [expression ["as" identifier]] ":" suite)+
  4. ["else" ":" suite]
  5. ["finally" ":" suite]
  6. try2_stmt ::= "try" ":" suite
  7. ("except" "*" expression ["as" identifier] ":" suite)+
  8. ["else" ":" suite]
  9. ["finally" ":" suite]
  10. try3_stmt ::= "try" ":" suite
  11. "finally" ":" suite

有關異常的更多信息可以在 異常 一節(jié)找到,有關使用 raise 語句生成異常的信息可以在 raise 語句 一節(jié)找到。

8.4.1. except clause

The 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

 
 
 
 
  1. except E as N:
  2. foo

被轉寫為

 
 
 
 
  1. except E as N:
  2. try:
  3. foo
  4. finally:
  5. 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 標準類型層級結構) 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:

 
 
 
 
  1. >>> print(sys.exc_info())
  2. (None, None, None)
  3. >>> try:
  4. ... raise TypeError
  5. ... except:
  6. ... print(sys.exc_info())
  7. ... try:
  8. ... raise ValueError
  9. ... except:
  10. ... print(sys.exc_info())
  11. ... print(sys.exc_info())
  12. ...
  13. (, TypeError(), )
  14. (, ValueError(), )
  15. (, TypeError(), )
  16. >>> print(sys.exc_info())
  17. (None, None, None)

8.4.2. except* clause

The 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.

 
 
 
 
  1. >>> try:
  2. ... raise ExceptionGroup("eg",
  3. ... [ValueError(1), TypeError(2), OSError(3), OSError(4)])
  4. ... except* TypeError as e:
  5. ... print(f'caught {type(e)} with nested {e.exceptions}')
  6. ... except* OSError as e:
  7. ... print(f'caught {type(e)} with nested {e.exceptions}')
  8. ...
  9. caught with nested (TypeError(2),)
  10. caught with nested (OSError(3), OSError(4))
  11. + Exception Group Traceback (most recent call last):
  12. | File "", line 2, in
  13. | ExceptionGroup: eg
  14. +-+---------------- 1 ----------------
  15. | ValueError: 1
  16. +------------------------------------

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.

 
 
 
 
  1. >>> try:
  2. ... raise BlockingIOError
  3. ... except* BlockingIOError as e:
  4. ... print(repr(e))
  5. ...
  6. 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.

8.4.3. else clause

如果控制流離開 try 子句體時沒有引發(fā)異常,并且沒有執(zhí)行 return, continue 或 break 語句,可選的 else 子句將被執(zhí)行。 else 語句中的異常不會由之前的 except 子句處理。

8.4.4. finally clause

If 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:

 
 
 
 
  1. >>> def f():
  2. ... try:
  3. ... 1/0
  4. ... finally:
  5. ... return 42
  6. ...
  7. >>> f()
  8. 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 tryfinally 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:

 
 
 
 
  1. >>> def foo():
  2. ... try:
  3. ... return 'try'
  4. ... finally:
  5. ... return 'finally'
  6. ...
  7. >>> foo()
  8. 'finally'

在 3.8 版更改: Prior to Python 3.8, a continue statement was illegal in the finally clause due to a problem with the implementation.

8.5. with 語句

with 語句用于包裝帶有使用上下文管理器 (參見 with 語句上下文管理器 一節(jié)) 定義的方法的代碼塊的執(zhí)行。 這允許對普通的 try…except…finally 使用模式進行封裝以方便地重用。

 
 
 
 
  1. with_stmt ::= "with" ( "(" with_stmt_contents ","? ")" | with_stmt_contents ) ":" suite
  2. with_stmt_contents ::= with_item ("," with_item)*
  3. with_item ::= expression ["as" target]

帶有一個“項目”的 with 語句的執(zhí)行過程如下:

  1. 對上下文表達式(在 with_item 中給出的表達式)進行求值來獲得上下文管理器。

  2. 載入上下文管理器的 __enter__() 以便后續(xù)使用。

  3. 載入上下文管理器的 __exit__() 以便后續(xù)使用。

  4. 發(fā)起調(diào)用上下文管理器的 __enter__() 方法。

  5. 如果 with 語句中包含一個目標,來自 __enter__() 的返回值將被賦值給它。

    備注

    with 語句會保證如果 __enter__() 方法返回時未發(fā)生錯誤,則 __exit__() 將總是被調(diào)用。 因此,如果在對目標列表賦值期間發(fā)生錯誤,則會將其視為在語句體內(nèi)部發(fā)生的錯誤。 參見下面的第 6 步。

  6. 執(zhí)行語句體。

  7. 發(fā)起調(diào)用上下文管理器的 __exit__() 方法。 如果語句體的退出是由異常導致的,則其類型、值和回溯信息將被作為參數(shù)傳遞給 __exit__()。 否則的話,將提供三個 None 參數(shù)。

    如果語句體的退出是由異常導致的,并且來自 __exit__() 方法的返回值為假,則該異常會被重新引發(fā)。 如果返回值為真,則該異常會被抑制,并會繼續(xù)執(zhí)行 with 語句之后的語句。

    如果語句體由于異常以外的任何原因退出,則來自 __exit__() 的返回值會被忽略,并會在該類退出正常的發(fā)生位置繼續(xù)執(zhí)行。

以下代碼:

 
 
 
 
  1. with EXPRESSION as TARGET:
  2. SUITE

在語義上等價于:

 
 
 
 
  1. manager = (EXPRESSION)
  2. enter = type(manager).__enter__
  3. exit = type(manager).__exit__
  4. value = enter(manager)
  5. hit_except = False
  6. try:
  7. TARGET = value
  8. SUITE
  9. except:
  10. hit_except = True
  11. if not exit(manager, *sys.exc_info()):
  12. raise
  13. finally:
  14. if not hit_except:
  15. exit(manager, None, None, None)

如果有多個項目,則會視作存在多個 with 語句嵌套來處理多個上下文管理器:

 
 
 
 
  1. with A() as a, B() as b:
  2. SUITE

在語義上等價于:

 
 
 
 
  1. with A() as a:
  2. with B() as b:
  3. SUITE

也可以用圓括號包圍的多行形式的多項目上下文管理器。例如:

 
 
 
 
  1. with (
  2. A() as a,
  3. B() as b,
  4. ):
  5. SUITE

在 3.1 版更改: 支持多個上下文表達式。

在 3.10 版更改: Support for using grouping parentheses to break the statement in multiple lines.

參見

PEP 343 - “with” 語句

Python with 語句的規(guī)范描述、背景和示例。

8.6. match 語句

3.10 新版功能.

匹配語句用于進行模式匹配。語法如下:

 
 
 
 
  1. match_stmt ::= 'match' subject_expr ":" NEWLINE INDENT case_block+ DEDENT
  2. subject_expr ::= star_named_expression "," star_named_expressions?
  3. | named_expression
  4. case_block ::= 'case' patterns [guard] ":" block

備注

本節(jié)使用單引號來表示 軟關鍵字。

模式匹配接受一個模式作為輸入(跟在 case 后),一個目標值(跟在 match 后)。該模式(可能包含子模式)將與目標值進行匹配。輸出是:

  • 匹配成功或失?。ㄒ脖环Q為模式成功或失敗)。

  • 可能將匹配的值綁定到一個名字上。 這方面的先決條件將在下面進一步討論。

關鍵字 matchcase 是 soft keywords 。

參見

  • PEP 634 —— 結構化模式匹配:規(guī)范

  • PEP 636 —— 結構化模式匹配:教程

8.6.1. 概述

匹配語句邏輯流程的概述如下:

  1. 對目標表達式 subject_expr 求值后將結果作為匹配用的目標值。 如果目標表達式包含逗號,則使用 the standard rules 構建一個元組。

  2. 目標值將依次與 case_block 中的每個模式進行匹配。匹配成功或失敗的具體規(guī)則在下面描述。匹配嘗試也可以與模式中的一些或所有的獨立名稱綁定。準確的模式綁定規(guī)則因模式類型而異,具體規(guī)定見下文。成功的模式匹配過程中產(chǎn)生的名稱綁定將超越所執(zhí)行的塊的范圍,可以在匹配語句之后使用。

    備注

    在模式匹配失敗時,一些子模式可能會成功。 不要依賴于失敗匹配進行的綁定。 反過來說,不要認為變量在匹配失敗后保持不變。 確切的行為取決于實現(xiàn),可能會有所不同。 這是一個有意的決定,允許不同的實現(xiàn)添加優(yōu)化。

  3. 如果該模式匹配成功,并且完成了對相應的約束項(如果存在)的求值。在這種情況下,保證完成所有的名稱綁定。

    • 如果約束項求值為真或缺失,執(zhí)行 case_block 中的 block

    • 否則,將按照上述方法嘗試下一個 case_block 。

    • 如果沒有進一步的 case 塊,匹配語句終止。

備注

用戶一般不應依賴正在求值的模式。 根據(jù)不同的實現(xiàn)方式,解釋器可能會緩存數(shù)值或使用其他優(yōu)化方法來避免重復求值。

匹配語句示例:

 
 
 
 
  1. >>> flag = False
  2. >>> match (100, 200):
  3. ... case (100, 300): # Mismatch: 200 != 300
  4. ... print('Case 1')
  5. ... case (100, 200) if flag: # Successful match, but guard fails
  6. ... print('Case 2')
  7. ... case (100, y): # Matches and binds y to 200
  8. ... print(f'Case 3, y: {y}')
  9. ... case _: # Pattern not attempted
  10. ... print('Case 4, I match anything!')
  11. ...
  12. Case 3, y: 200

在這個示例中,if flag 是約束項。請閱讀下一節(jié)以了解更多相關內(nèi)容。

8.6.2. 約束項

 
 
 
 
  1. guard ::= "if" named_expression

guard (它是 case 的一部分) 必須成立才能讓 case 語句塊中的代碼被執(zhí)行。 它所采用的形式為: if 之后跟一個表達式。

擁有 guardcase 塊的邏輯流程如下:

  1. 檢查 case 塊中的模式是否匹配成功。如果該模式匹配失敗,則不對 guard 進行求值,檢查下一個 case 塊。

  2. 如果該模式匹配成功,對 guard 求值。

    • 如果 guard 求值為真,則選用該 case 塊。

    • 如果 guard 求值為假,則不選用該 case 塊。

    • 如果在對 guard 求值過程中引發(fā)了異常,則異常將被拋出。

允許約束項產(chǎn)生副作用,因為他們是表達式。約束項求值必須從第一個 case 塊到最后一個 case 塊依次逐個進行,模式匹配失敗的 case 塊將被跳過。(也就是說,約束項求值必須按順序進行。)一旦選用了一個 case 塊,約束項求值必須由此終止。

8.6.3. 必定匹配的 case 塊

必定匹配的 case 塊是能匹配所有情況的 case 塊。一個匹配語句最多可以有一個必定匹配的 case 塊,而且必須是最后一個。

如果一個 case 塊沒有約束項,并且其模式是必定匹配的,那么它就被認為是必定匹配的。 如果我們可以僅從語法上證明一個模式總是能匹配成功,那么這個模式就被認為是必定匹配的。 只有以下模式是必定匹配的:

  • 左側模式是必定匹配的 AS 模式

  • 包含至少一個必定匹配模式的 或模式

  • 捕獲模式

  • 通配符模式

  • 括號內(nèi)的必定匹配模式

8.6.4. 模式

備注

本節(jié)使用了超出標準 EBNF 的語法符號。

  • 符號 SEP.RULE+RULE (SEP RULE)* 的簡寫

  • 符號 !RULE 是前向否定斷言的簡寫

patterns 的頂層語法是:

 
 
 
 
  1. patterns ::= open_sequence_pattern | pattern
  2. pattern ::= as_pattern | or_pattern
  3. closed_pattern ::= | literal_pattern
  4. | capture_pattern
  5. | wildcard_pattern
  6. | value_pattern
  7. | group_pattern
  8. | sequence_pattern
  9. | mapping_pattern
  10. | class_pattern

下面的描述將包括一個“簡而言之”以描述模式的作用,便于說明問題(感謝 Raymond Hettinger 提供的一份文件,大部分的描述受其啟發(fā))。請注意,這些描述純粹是為了說明問題,可能不 反映底層的實現(xiàn)。此外,它們并沒有涵蓋所有有效的形式。

8.6.4.1. 或模式

或模式是由豎杠 | 分隔的兩個或更多的模式。語法:

 
 
 
 
  1. or_pattern ::= "|".closed_pattern+

只有最后的子模式可以是 必定匹配的,且每個子模式必須綁定相同的名字集以避免歧義。

或模式將目標值依次與其每個子模式嘗試匹配,直到有一個匹配成功,然后該或模式被視作匹配成功。 否則,如果沒有任何子模式匹配成功,則或模式匹配失敗。

簡而言之,P1 | P2 | ... 會首先嘗試匹配 P1 ,如果失敗將接著嘗試匹配 P2 ,如果出現(xiàn)成功的匹配則立即結束且模式匹配成功,否則模式匹配失敗。

8.6.4.2. AS 模式

AS 模式將關鍵字 as 左側的或模式與目標值進行匹配。語法:

 
 
 
 
  1. as_pattern ::= or_pattern "as" capture_pattern

如果或模式匹配失敗,AS 模式也匹配失敗。 否則,AS 模式將目標與關鍵字 as 右邊的名字綁定且匹配陳成功。 capture_pattern 不能是 _ 。

簡而言之, P as NAME 將與 P 匹配,成功后將設置 NAME =

8.6.4.3. 字面值模式

字面值模式對應 Python 中的大多數(shù) 字面值。 語法為:

 
 
 
 
  1. literal_pattern ::= signed_number
  2. | signed_number "+" NUMBER
  3. | signed_number "-" NUMBER
  4. | strings
  5. | "None"
  6. | "True"
  7. | "False"
  8. | signed_number: NUMBER | "-" NUMBER

規(guī)則 strings 和標記 NUMBER 是在 standard Python grammar 中定義的。支持三引號的字符串。不支持原始字符串和字節(jié)字符串。也不支持 格式字符串字面值 。

signed_number '+' NUMBERsigned_number '-' NUMBER 形式是用于表示 復數(shù);它們要求左邊是一個實數(shù)而右邊是一個虛數(shù)。 例如 3 + 4j。

簡而言之, LITERAL 只會在 == LITERAL 時匹配成功。對于單例 None 、 TrueFalse ,會使用 is 運算符。

8.6.4.4. 捕獲模式

捕獲模式將目標值與一個名稱綁定。語法:

 
 
 
 
  1. capture_pattern ::= !'_' NAME

單獨的一個下劃線 _ 不是捕獲模式( !'_' 表達的就是這個含義)。 它會被當作 wildcard_pattern 。

在給定的模式中,一個名字只能被綁定一次。例如 case x, x: ... 時無效的,但 case [x] | x: ... 是被允許的。

捕獲模式總是能匹配成功。綁定遵循 PEP 572 中賦值表達式運算符設立的作用域規(guī)則;名字在最接近的包含函數(shù)作用域內(nèi)成為一個局部變量,除非有適用的 global 或 nonlocal 語句。

簡而言之, NAME 總是會匹配成功且將設置 NAME = 。

8.6.4.5. 通配符模式

通配符模式總是會匹配成功(匹配任何內(nèi)容)并且不綁定任何名稱。語法:

 
 
 
 
  1. wildcard_pattern ::= '_'

在且僅在任何模式中 _ 是一個 軟關鍵字。 通常情況下它是一個標識符,即使是在 match 的目標表達式、guardcase 代碼塊中也是如此。

簡而言之,_ 總是會匹配成功。

8.6.4.6. 值模式

值模式代表 Python 中具有名稱的值。語法:

 
 
 
 
  1. value_pattern ::= attr
  2. attr ::= name_or_attr "." NAME
  3. name_or_attr ::= attr | NAME

模式中帶點的名稱會使用標準的 Python 名稱解析規(guī)則 來查找。 如果找到的值與目標值比較結果相等則模式匹配成功(使用 == 相等運算符)。

簡而言之, NAME1.NAME2 僅在 == NAME1.NAME2 時匹配成功。

備注

如果相同的值在同一個匹配語句中出現(xiàn)多次,解釋器可能會緩存找到的第一個值并重新使用它,而不是重復查找。 這種緩存與特定匹配語句的執(zhí)行嚴格掛鉤。

8.6.4.7. 組模式

組模式允許用戶在模式周圍添加括號,以強調(diào)預期的分組。 除此之外,它沒有額外的語法。語法:

 
 
 
 
  1. group_pattern ::= "(" pattern ")"

簡單來說 (P) 具有與 P 相同的效果。

8.6.4.8. 序列模式

一個序列模式包含數(shù)個將與序列元素進行匹配的子模式。其語法類似于列表或元組的解包。

 
 
 
 
  1. sequence_pattern ::= "[" [maybe_sequence_pattern] "]"
  2. | "(" [open_sequence_pattern] ")"
  3. open_sequence_pattern ::= maybe_star_pattern "," [maybe_sequence_pattern]
  4. maybe_sequence_pattern ::= ",".maybe_star_pattern+ ","?
  5. maybe_star_pattern ::= star_pattern | pattern
  6. star_pattern ::= "*" (capture_pattern | wildcard_pattern)

序列模式中使用圓括號或方括號沒有區(qū)別(例如 (...)[...] )。

備注

用圓括號括起來且沒有跟隨逗號的單個模式 (例如 (3 | 4)) 是一個 分組模式。 而用方括號括起來的單個模式 (例如 [3 | 4]) 則仍是一個序列模式。

一個序列模式中最多可以有一個星號子模式。星號子模式可以出現(xiàn)在任何位置。如果沒有星號子模式,該序列模式是固定長度的序列模式;否則,其是一個可變長度的序列模式。

下面是將一個序列模式與一個目標值相匹配的邏輯流程:

  1. 如果目標值不是一個序列 2 ,該序列模式匹配失敗。

  2. 如果目標值是 str 、 bytesbytearray 的實例,則該序列模式匹配失敗。

  3. 隨后的步驟取決于序列模式是固定長度還是可變長度的。

    如果序列模式是固定長度的:

    1. 如果目標序列的長度與子模式的數(shù)量不相等,則該序列模式匹配失敗

    2. 序列模式中的子模式與目標序列中的相應項目從左到右進行匹配。 一旦一個子模式匹配失敗,就停止匹配。 如果所有的子模式都成功地與它們的對應項相匹配,那么該序列模式就匹配成功了。

    否則,如果序列模式是變長的:

    1. 如果目標序列的長度小于非星號子模式的數(shù)量,則該序列模式匹配失敗。

    2. 與固定長度的序列一樣,靠前的非星形子模式與其相應的項目進行匹配。

    3. 如果上一步成功,星號子模式與剩余的目標項形成的列表相匹配,不包括星號子模式之后的非星號子模式所對應的剩余項。

    4. 剩余的非星號子模式將與相應的目標項匹配,就像固定長度的序列一樣。

    備注

    目標序列的長度可通過 len() (即通過 __len__() 協(xié)議) 獲得。 解釋器可能會以類似于 值模式 的方式緩存這個長度信息。

簡而言之, [P1, P2, P3,, P] 僅在滿足以下情況時匹配成功:

  • 檢查 是一個序列

  • len(subject) ==

  • P1[0] 進行匹配(請注意此匹配可以綁定名稱)

  • P2[1] 進行匹配(請注意此匹配可以綁定名稱)

  • …… 剩余對應的模式/元素也以此類推。

8.6.4.9. 映射模式

映射模式包含一個或多個鍵值模式。其語法類似于字典的構造。語法:

 
 
 
 
  1. mapping_pattern ::= "{" [items_pattern] "}"
  2. items_pattern ::= ",".key_value_pattern+ ","?
  3. key_value_pattern ::= (literal_pattern | value_pattern) ":" pattern
  4. | double_star_pattern
  5. double_star_pattern ::= "**" capture_pattern

一個映射模式中最多可以有一個雙星號模式。雙星號模式必須是映射模式中的最后一個子模式。

映射模式中不允許出現(xiàn)重復的鍵。重復的字面值鍵會引發(fā) SyntaxError 。若是兩個鍵有相同的值將會在運行時引發(fā) ValueError 。

以下是映射模式與目標值匹配的邏輯流程:

  1. 如果目標值不是一個映射 3,則映射模式匹配失敗。

  2. 若映射模式中給出的每個鍵都存在于目標映射中,且每個鍵的模式都與目標映射的相應項匹配成功,則該映射模式匹配成功。

  3. 如果在映射模式中檢測到重復的鍵,該模式將被視作無效。對于重復的字面值,會引發(fā) SyntaxError ;對于相同值的命名鍵,會引發(fā) ValueError 。

備注

鍵值對使用映射目標的 get() 方法的雙參數(shù)形式進行匹配。匹配的鍵值對必須已經(jīng)存在于映射中,而不是通過 __missing__()__getitem__() 即時創(chuàng)建。

簡而言之, {KEY1: P1, KEY2: P2, ... } 僅在滿足以下情況時匹配成功:

  • 檢查 是映射

  • KEY1 in

  • P1[KEY1] 相匹配

  • …… 剩余對應的鍵/模式對也以此類推。

8.6.4.10. 類模式

類模式表示一個類以及它的位置參數(shù)和關鍵字參數(shù)(如果有的話)。語法:

 
 
 
 
  1. class_pattern ::= name_or_attr "(" [pattern_arguments ","?] ")"
  2. pattern_arguments ::= positional_patterns ["," keyword_patterns]
  3. | keyword_patterns
  4. positional_patterns ::= ",".pattern+
  5. keyword_patterns ::= ",".keyword_pattern+
  6. keyword_pattern ::= NAME "=" pattern

同一個關鍵詞不應該在類模式中重復出現(xiàn)。

以下是類模式與目標值匹配的邏輯流程:

  1. 如果 name_or_attr 不是內(nèi)置 type 的實例,引發(fā) TypeError 。

  2. 如果目標值不是 name_or_attr 的實例(通過 isinstance() 測試),該類模式匹配失敗。

  3. 如果沒有模式參數(shù)存在,則該模式匹配成功。 否則,后面的步驟取決于是否有關鍵字或位置參數(shù)模式存在。

    對于一些內(nèi)置的類型(將在后文詳述),接受一個位置子模式,它將與整個目標值相匹配;對于這些類型,關鍵字模式也像其他類型一樣工作。

    如果只存在關鍵詞模式,它們將被逐一處理,如下所示:

    一. 該關鍵詞被視作主體的一個屬性進行查找。

    • 如果這引發(fā)了除 AttributeError 以外的異常,該異常會被拋出。

    • 如果這引發(fā)了 AttributeError ,該類模式匹配失敗。

    • 否則,與關鍵詞模式相關的子模式將與目標的屬性值進行匹配。 如果失敗,則類模式匹配失??;如果成功,則繼續(xù)對下一個關鍵詞進行匹配。

    二. 如果所有的關鍵詞模式匹配成功,該類模式匹配成功。

    如果存在位置模式,在匹配前會用類 name_or_attr 的 __match_args__ 屬性將其轉換為關鍵詞模式。

    一. 進行與 getattr(cls, "__match_args__", ()) 等價的調(diào)用。

    • 如果這引發(fā)一個異常,該異常將被拋出。

    • 如果返回值不是一個元組,則轉換失敗且引發(fā) TypeError 。

    • 若位置模式的數(shù)量超出 len(cls.__match_args__) ,將引發(fā) TypeError 。

    • 否則,位置模式 i 會使用 __match_args__[i] 轉換為關鍵詞。 __match_args__[i] 必須是一個字符串;如果不是則引發(fā) TypeError 。

    • 如果有重復的關鍵詞,引發(fā) TypeError 。

    參見

    定制類模式匹配中的位置參數(shù)

    二. 若所有的位置模式都被轉換為關鍵詞模式,

    匹配的過程就像只有關鍵詞模式一樣。

    對于以下內(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) 僅在滿足以下情況時匹配成功:

  • isinstance(, CLS)

  • CLS.__match_args__P1 轉換為關鍵詞模式

  • 對于每個關鍵詞參數(shù) attr=P2

    • hasattr(, "attr")

    • P2.attr 進行匹配

  • …… 剩余對應的關鍵字參數(shù)/模式對也以此類推。

參見

  • PEP 634 —— 結構化模式匹配:規(guī)范

  • PEP 636 —— 結構化模式匹配:教程

8.7. 函數(shù)定義

函數(shù)定義就是對用戶自定義函數(shù)的定義(參見 標準類型層級結構 一節(jié)):

 
 
 
 
  1. funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")"
  2. ["->" expression] ":" suite
  3. decorators ::= decorator+
  4. decorator ::= "@" assignment_expression NEWLINE
  5. parameter_list ::= defparameter ("," defparameter)* "," "/" ["," [parameter_list_no_posonly]]
  6. | parameter_list_no_posonly
  7. parameter_list_no_posonly ::= defparameter ("," defparameter)* ["," [parameter_list_starargs]]
  8. | parameter_list_starargs
  9. parameter_list_starargs ::= "*" [parameter] ("," defparameter)* ["," ["**" parameter [","]]]
  10. | "**" parameter [","]
  11. parameter ::= identifier [":" expression]
  12. defparameter ::= parameter ["=" expression]
  13. funcname ::= identifier

函數(shù)定義是一條可執(zhí)行語句。 它執(zhí)行時會在當前局部命名空間中將函數(shù)名稱綁定到一個函數(shù)對象(函數(shù)可執(zhí)行代碼的包裝器)。 這個函數(shù)對象包含對當前全局命名空間的引用,作為函數(shù)被調(diào)用時所使用的全局命名空間。

函數(shù)定義并不會執(zhí)行函數(shù)體;只有當函數(shù)被調(diào)用時才會執(zhí)行此操作。 4

一個函數(shù)定義可以被一
本文題目:創(chuàng)新互聯(lián)Python教程:8.復合語句
鏈接地址:http://m.5511xx.com/article/cccphgc.html