天天看點

#yyds幹貨盤點#python pass和match

​pass​

​ 語句不執行任何操作。文法上需要一個語句,但程式不實際執行任何動作時,可以使用該語句。例如:

>>> while True:
...     pass  # Busy-wait for keyboard interrupt (Ctrl+C)
...      

下面這段代碼建立了一個最小的類:

>>> class MyEmptyClass:
...     pass
...      

​pass​

​​ 還可以用作函數或條件子句的占位符,讓開發者聚焦更抽象的層次。此時,程式直接忽略 ​

​pass​

​:>>>

>>> def initlog(*args):
...     pass   # Remember to implement this!
...      

 ​

​match​

​ 語句

A ​

​match​

​ statement takes an expression and compares its value to successive patterns given as one or more case blocks. This is superficially similar to a switch statement in C, Java or JavaScript (and many other languages), but it can also extract components (sequence elements or object attributes) from the value into variables.

最簡單的形式是将一個目标值與一個或多個字面值進行比較:

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:
            return "Something's wrong with the internet"      

注意最後一個代碼塊:“變量名” ​

​_​

​ 被作為 通配符 并必定會比對成功。 如果沒有 case 語句比對成功,則不會執行任何分支。使用 ​

​|​

​ (“ or ”)在一個模式中可以組合多個字面值:

case 401 | 403 | 404:
    return "Not allowed"      

模式的形式類似解包指派,并可被用于綁定變量:

# point is an (x, y) tuple
match point:
    case (0, 0):
        print("Origin")
    case (0, y):
        print(f"Y={y}")
    case (x, 0):
        print(f"X={x}")
    case (x, y):
        print(f"X={x}, Y={y}")
    case _:
        raise ValueError("Not a point")      

請仔細研究此代碼! 第一個模式有兩個字面值,可以看作是上面所示字面值模式的擴充。但接下來的兩個模式結合了一個字面值和一個變量,而變量 綁定 了一個來自目标的值(​

​point​

​​)。第四個模式捕獲了兩個值,這使得它在概念上類似于解包指派 ​

​(x, y) = point​

​。

如果使用類實作資料結構,可在類名後加一個類似于構造器的參數清單,這樣做可以把屬性放到變量裡:

class Point:
    x: int
    y: int

def where_is(point):
    match point:
        case Point(x=0, y=0):
            print("Origin")
        case Point(x=0, y=y):
            print(f"Y={y}")
        case Point(x=x, y=0):
            print(f"X={x}")
        case Point():
            print("Somewhere else")
        case _:
            print("Not a point")      

可在 dataclass 等支援屬性排序的内置類中使用位置參數。還可在類中設定 ​

​__match_args__​

​​ 特殊屬性為模式的屬性定義指定位置。如果它被設為 ("x", "y"),則以下模式均為等價的,并且都把 ​

​y​

​​ 屬性綁定到 ​

​var​

​ 變量:

Point(1, var)
Point(1, y=var)
Point(x=1, y=var)
Point(y=var, x=1)      

讀取模式的推薦方式是将它們看做是你會在指派操作左側放置的内容的擴充形式,以便了解各個變量将會被設定的值。 隻有單獨的名稱(例如上面的 ​

​var​

​​)會被 match 語句所指派。 帶點号的名稱 (例如 ​

​foo.bar​

​​)、屬性名稱(例如上面的 ​

​x=​

​​ 和 ​

​y=​

​​)或類名稱(通過其後的 "(...)" 來識别,例如上面的 ​

​Point​

​)都絕不會被指派。

match points:
    case []:
        print("No points")
    case [Point(0, 0)]:
        print("The origin")
    case [Point(x, y)]:
        print(f"Single point {x}, {y}")
    case [Point(0, y1), Point(0, y2)]:
        print(f"Two on the Y axis at {y1}, {y2}")
    case _:
        print("Something else")      
match point:
    case Point(x, y) if x == y:
        print(f"Y=X at {x}")
    case Point(x, y):
        print(f"Not on the diagonal")      
  • 與解包指派類似,元組和清單模式具有完全相同的含義,并且實際上能比對任意序列。 但它們不能比對疊代器或字元串。
  • 序列模式支援擴充解包操作:​

    ​[x, y, *rest]​

    ​​和​

    ​(x, y, *rest)​

    ​​的作用類似于解包指派。 在​

    ​*​

    ​​之後的名稱也可以為​

    ​_​

    ​​,是以,​

    ​(x, y, *_)​

    ​可以比對包含至少兩個條目的序列,而不必綁定其餘的條目。
  • Mapping patterns:​

    ​{"bandwidth": b, "latency": l}​

    ​​captures the​

    ​"bandwidth"​

    ​​and​

    ​"latency"​

    ​​values from a dictionary. Unlike sequence patterns, extra keys are ignored. An unpacking like​

    ​**rest​

    ​​is also supported. (But​

    ​**_​

    ​would be redundant, so it is not allowed.)
  • 使用​

    ​as​

    ​關鍵字可以捕獲子模式:
case (Point(x1, y1), Point(x2, y2) as p2): ...      
  • 将把輸入的第二個元素捕獲為​

    ​p2​

    ​(隻要輸入是包含兩個點的序列)
  • 大多數字面值是按相等性比較的,但是單例對象​

    ​True​

    ​​,​

    ​False​

    ​​和​

    ​None​

    ​則是按辨別号比較的。
  • 模式可以使用命名常量。 這些命名常量必須為帶點号的名稱以防止它們被解讀為捕獲變量:
from enum import Enum
class Color(Enum):
    RED = 'red'
    GREEN = 'green'
    BLUE = 'blue'

color = Color(input("Enter your choice of 'red', 'blue' or 'green': "))

match color:
    case Color.RED:
        print("I see red!")
    case Color.GREEN:
        print("Grass is green")
    case Color.BLUE:
        print("I'm feeling the blues :(")