دستور match یک عبارت را میگیرد و مقدار آن را با الگوهای متوالی داده شده به عنوان بلوکهای case مقایسه میکند. این به طور سطحی شبیه به دستور switch در C، Java یا JavaScript است، اما بیشتر شبیه تطبیق الگو در زبانهایی مانند Rust یا هسکل است. فقط اولین الگوی مطابقتدار اجرا میشود و میتواند هم مقادیر (عناصر توالی یا ویژگیهای شیء) را در متغیرها استخراج کند. اگر هیچ case ای مطابقت نداشته باشد، هیچکدام از شاخهها اجرا نمیشوند.
سادهترین فرم یک مقدار موضوع را با یک یا چند لیترال مقایسه میکند:
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"
توجه به بلوک آخر: "نام متغیر" _ به عنوان یک wildcard (بینهایت) عمل میکند و هرگز مطابقت نمییابد.
شما میتوانید چندین لیترال را در یک الگوی واحد با استفاده از | ("یا") ترکیب کنید:
case 401 | 403 | 404:
return "Not allowed"
الگوهای میتوانند شبیه انتسابهای بازپاکسازی (unpacking assignments) به نظر برسند و میتوانند برای اتصال متغیرها استفاده شوند:
# point یک تاپل (x, y) است
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:
def __init__(self, x, y):
self.x = x
self.y = y
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")
میتوانید از پارامترهای موقعیتی با برخی کلاسهای داخلی که یک ترتیب برای ویژگیهایشان فراهم میکنند (مثلاً dataclasses) استفاده کنید. همچنین میتوانید یک موقعیت خاص برای ویژگیها در الگوها با تنظیم ویژگی خاص __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) هرگز به متغیرها اختصاص داده نمیشوند.
الگوهای میتوانند به طور دلخواه تودرتو باشند. برای مثال، اگر لیست کوتاهی از Points با __match_args__ اضافه شده داشته باشیم، میتوانیم آن را مانند زیر تطبیق دهیم:
class Point:
__match_args__ = ('x', 'y')
def __init__(self, x, y):
self.x = x
self.y = y
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")
میتوانیم یک بند if به یک الگو اضافه کنیم، که به آن «گارد» (guard) معروف است. اگر گارد نادرست باشد، match برای امتحان بلوک case بعدی ادامه میدهد. توجه کنید که اتصال مقدار قبل از ارزیابی گارد اتفاق میافتد:
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, *_) توالیای با حداقل دو آیتم را بدون اتصال آیتمهای باقیمانده تطبیق میدهد.{"bandwidth": b, "latency": l} مقادیر "bandwidth" و "latency" را از یک دیکشنری استخراج میکند. برخلاف الگوهای توالی، کلیدهای اضافه نادیده گرفته میشوند. بازپاکسازی مانند **rest هم پشتیبانی میشود. (اما **_ زائد خواهد بود، بنابراین مجاز نیست.)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 :(")
برای توضیح دقیقتر و مثالهای بیشتر، میتوانید به PEP 636 مراجعه کنید که به فرمت آموزشی نوشته شده است.
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://docs.python.org/3/tutorial