ವಿಷಯಕ್ಕೆ ತೆರಳಿ

ಸ್ಟ್ರಕ್ಚರಲ್ ಪ್ಯಾಟರ್ನ್ ಮ್ಯಾಚಿಂಗ್ (Structural Pattern Matching)

ಪೈಥಾನ್ 3.10 ರಲ್ಲಿ ಪರಿಚಯಿಸಲಾದ ಸ್ಟ್ರಕ್ಚರಲ್ ಪ್ಯಾಟರ್ನ್ ಮ್ಯಾಚಿಂಗ್ (match ಮತ್ತು case ಸ್ಟೇಟ್‌ಮೆಂಟ್‌ಗಳು) ಒಂದು ಶಕ್ತಿಯುತವಾದ ನಿಯಂತ್ರಣ ಹರಿವಿನ (control flow) ಸಾಧನವಾಗಿದೆ. ಇದು ಇತರ ಭಾಷೆಗಳಲ್ಲಿರುವ switch ಸ್ಟೇಟ್‌ಮೆಂಟ್‌ಗೆ ಹೋಲುತ್ತದೆ, ಆದರೆ ಇದು ಕೇವಲ ಮೌಲ್ಯಗಳನ್ನು ಹೋಲಿಸುವುದಕ್ಕಿಂತ ಹೆಚ್ಚು ಸಾಮರ್ಥ್ಯವನ್ನು ಹೊಂದಿದೆ. ಇದು ಡೇಟಾದ ರಚನೆ (structure) ಯನ್ನು ಆಧರಿಸಿ ಮ್ಯಾಚ್ ಮಾಡುತ್ತದೆ.

ಮೂಲ ಸಿಂಟ್ಯಾಕ್ಸ್

match ಸ್ಟೇಟ್‌ಮೆಂಟ್ ಒಂದು ವಿಷಯವನ್ನು (subject) ತೆಗೆದುಕೊಳ್ಳುತ್ತದೆ ಮತ್ತು ಅದನ್ನು case ಬ್ಲಾಕ್‌ಗಳಲ್ಲಿರುವ ಹಲವು ಪ್ಯಾಟರ್ನ್‌ಗಳೊಂದಿಗೆ ಹೋಲಿಸುತ್ತದೆ.

match subject:
    case <pattern_1>:
        # ಪ್ಯಾಟರ್ನ್ 1 ಮ್ಯಾಚ್ ಆದರೆ ಈ ಕೋಡ್ ಚಲಿಸುತ್ತದೆ
    case <pattern_2>:
        # ಪ್ಯಾಟರ್ನ್ 2 ಮ್ಯಾಚ್ ಆದರೆ ಈ ಕೋಡ್ ಚಲಿಸುತ್ತದೆ
    case _:
        # ಯಾವುದೇ ಪ್ಯಾಟರ್ನ್ ಮ್ಯಾಚ್ ಆಗದಿದ್ದರೆ ಈ ಕೋಡ್ ಚಲಿಸುತ್ತದೆ (ಡೀಫಾಲ್ಟ್)
  • _ (underscore) ಒಂದು ವೈಲ್ಡ್‌ಕಾರ್ಡ್ ಪ್ಯಾಟರ್ನ್. ಇದು ಯಾವುದೇ ಮೌಲ್ಯಕ್ಕೆ ಮ್ಯಾಚ್ ಆಗುತ್ತದೆ ಮತ್ತು ಇದನ್ನು ಸಾಮಾನ್ಯವಾಗಿ ಡೀಫಾಲ್ಟ್ ಕೇಸ್‌ಗಾಗಿ ಬಳಸಲಾಗುತ್ತದೆ.

1. ಲಿಟರಲ್ ಪ್ಯಾಟರ್ನ್‌ಗಳು (Literal Patterns)

ಇದು ಸರಳವಾದ ಪ್ಯಾಟರ್ನ್. ಇದು ನಿರ್ದಿಷ್ಟ ಮೌಲ್ಯಗಳಿಗೆ (ಸಂಖ್ಯೆ, ಸ್ಟ್ರಿಂಗ್, True, False, None) ಮ್ಯಾಚ್ ಮಾಡುತ್ತದೆ.

ಉದಾಹರಣೆ: HTTP ಸ್ಟೇಟಸ್ ಕೋಡ್ ಅನ್ನು ಪರಿಶೀಲಿಸುವುದು.

def http_status(status):
    match status:
        case 200:
            return "OK"
        case 404:
            return "Not Found"
        case 500:
            return "Internal Server Error"
        case _:
            return "Unknown Status"

print(http_status(200))  # ಔಟ್‌ಪುಟ್: OK
print(http_status(404))  # ಔಟ್‌ಪುಟ್: Not Found
print(http_status(403))  # ಔಟ್‌ಪುಟ್: Unknown Status

2. OR ಪ್ಯಾಟರ್ನ್‌ಗಳು (|)

ಒಂದೇ case ಬ್ಲಾಕ್‌ನಲ್ಲಿ ಹಲವು ಲಿಟರಲ್ ಪ್ಯಾಟರ್ನ್‌ಗಳನ್ನು ಸಂಯೋಜಿಸಲು | (OR) ಆಪರೇಟರ್ ಅನ್ನು ಬಳಸಬಹುದು.

ಉದಾಹರಣೆ:

def check_day(day):
    match day:
        case "ಶನಿವಾರ" | "ಭಾನುವಾರ":
            print("ಇದು ವಾರಾಂತ್ಯ!")
        case "ಸೋಮವಾರ" | "ಮಂಗಳವಾರ" | "ಬುಧವಾರ" | "ಗುರುವಾರ" | "ಶುಕ್ರವಾರ":
            print("ಇದು ವಾರದ ದಿನ.")
        case _:
            print("ದಯವಿಟ್ಟು ಸರಿಯಾದ ದಿನವನ್ನು ನಮೂದಿಸಿ.")

check_day("ಭಾನುವಾರ") # ಔಟ್‌ಪುಟ್: ಇದು ವಾರಾಂತ್ಯ!

3. ಕ್ಯಾಪ್ಚರ್ ಪ್ಯಾಟರ್ನ್‌ಗಳು (Capture Patterns)

ಒಂದು ವೇರಿಯೇಬಲ್ ಹೆಸರನ್ನು ಪ್ಯಾಟರ್ನ್ ಆಗಿ ಬಳಸಿದರೆ, ಅದು ಯಾವುದೇ ಮೌಲ್ಯಕ್ಕೆ ಮ್ಯಾಚ್ ಆಗುತ್ತದೆ ಮತ್ತು ಆ ಮೌಲ್ಯವನ್ನು ಆ ವೇರಿಯೇಬಲ್‌ಗೆ przypisuje (assign).

ಉದಾಹರಣೆ:

def process_command(command):
    match command.split():
        case ["load", filename]:
            print(f"'{filename}' ಫೈಲ್ ಅನ್ನು ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ...")
        case ["save", filename]:
            print(f"'{filename}' ಫೈಲ್ ಅನ್ನು ಸೇವ್ ಮಾಡಲಾಗುತ್ತಿದೆ...")
        case ["quit"]:
            print("ಪ್ರೋಗ್ರಾಂನಿಂದ ನಿರ್ಗಮಿಸಲಾಗುತ್ತಿದೆ.")
        case _:
            print("ಅಮಾನ್ಯ ಕಮಾಂಡ್.")

process_command("load my_data.csv") # ಔಟ್‌ಪುಟ್: 'my_data.csv' ಫೈಲ್ ಅನ್ನು ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ...
ಇಲ್ಲಿ, filename ಒಂದು ಕ್ಯಾಪ್ಚರ್ ಪ್ಯಾಟರ್ನ್.

4. ಸೀಕ್ವೆನ್ಸ್ ಪ್ಯಾಟರ್ನ್‌ಗಳು (Sequence Patterns)

ಇದು ಲಿಸ್ಟ್‌ಗಳು (lists) ಮತ್ತು ಟ್ಯೂಪಲ್‌ಗಳ (tuples) ರಚನೆಯನ್ನು ಮ್ಯಾಚ್ ಮಾಡಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ.

ಉದಾಹರಣೆ:

def process_data(data):
    match data:
        case []:
            print("ಖಾಲಿ ಪಟ್ಟಿ.")
        case [x]:
            print(f"ಒಂದು ಅಂಶವಿದೆ: {x}")
        case [x, y]:
            print(f"ಎರಡು ಅಂಶಗಳಿವೆ: {x} ಮತ್ತು {y}")
        case [x, *rest]:
            print(f"ಮೊದಲ ಅಂಶ: {x}, ಉಳಿದವು: {rest}")
        case _:
            print("ಇತರ ರೀತಿಯ ಡೇಟಾ.")

process_data([])              # ಔಟ್‌ಪುಟ್: ಖಾಲಿ ಪಟ್ಟಿ.
process_data([10])            # ಔಟ್‌ಪುಟ್: ಒಂದು ಅಂಶವಿದೆ: 10
process_data([10, 20])        # ಔಟ್‌ಪುಟ್: ಎರಡು ಅಂಶಗಳಿವೆ: 10 ಮತ್ತು 20
process_data([10, 20, 30, 40]) # ಔಟ್‌ಪುಟ್: ಮೊದಲ ಅಂಶ: 10, ಉಳಿದವು: [20, 30, 40]
*rest ಎಂಬುದು "ಸ್ಟಾರ್ ಪ್ಯಾಟರ್ನ್", ಇದು ಸೀಕ್ವೆನ್ಸ್‌ನ ಉಳಿದ ಎಲ್ಲಾ ಅಂಶಗಳನ್ನು ಒಂದು ಲಿಸ್ಟ್ ಆಗಿ ಸಂಗ್ರಹಿಸುತ್ತದೆ.

5. ಮ್ಯಾಪಿಂಗ್ ಪ್ಯಾಟರ್ನ್‌ಗಳು (Mapping Patterns)

ಇದು ಡಿಕ್ಷನರಿಗಳ (dictionaries) ರಚನೆಯನ್ನು ಮ್ಯಾಚ್ ಮಾಡಲು ಬಳಸಲಾಗುತ್ತದೆ.

ಉದಾಹರಣೆ:

def process_user(user):
    match user:
        case {"name": name, "email": email}:
            print(f"ಬಳಕೆದಾರ: {name}, ಇಮೇಲ್: {email}")
        case {"name": name, "role": "admin"}:
            print(f"ನಿರ್ವಾಹಕ: {name}")
        case {"name": name}:
            print(f"ಬಳಕೆದಾರ: {name}, ಇತರ ಮಾಹಿತಿ ಲಭ್ಯವಿಲ್ಲ.")
        case _:
            print("ಅಮಾನ್ಯ ಬಳಕೆದಾರ ಡೇಟಾ.")

process_user({"name": "ರವಿ", "email": "ravi@example.com"})
# ಔಟ್‌ಪುಟ್: ಬಳಕೆದಾರ: ರವಿ, ಇಮೇಲ್: ravi@example.com

process_user({"name": "ನಿಶ್ಚಲ", "role": "admin", "city": "Hassan"})
# ಔಟ್‌ಪುಟ್: ನಿರ್ವಾಹಕ: ನಿಶ್ಚಲ

6. ಕ್ಲಾಸ್ ಪ್ಯಾಟರ್ನ್‌ಗಳು (Class Patterns)

ಇದು ಆಬ್ಜೆಕ್ಟ್‌ಗಳ ಪ್ರಕಾರ ಮತ್ತು ಅವುಗಳ ಗುಣಲಕ್ಷಣಗಳನ್ನು (attributes) ಮ್ಯಾಚ್ ಮಾಡಲು ಬಳಸಲಾಗುತ್ತದೆ.

ಉದಾಹರಣೆ:

from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int

def describe_point(p):
    match p:
        case Point(x=0, y=0):
            print("ಇದು ಮೂಲ (Origin).")
        case Point(x=0, y=y):
            print(f"ಇದು Y-ಅಕ್ಷದ ಮೇಲಿದೆ, y={y}.")
        case Point(x=x, y=0):
            print(f"ಇದು X-ಅಕ್ಷದ ಮೇಲಿದೆ, x={x}.")
        case Point(x=x, y=y):
            print(f"ಪಾಯಿಂಟ್ ({x}, {y}) ನಲ್ಲಿದೆ.")
        case _:
            print("ಇದು ಪಾಯಿಂಟ್ ಅಲ್ಲ.")

describe_point(Point(0, 5))  # ಔಟ್‌ಪುಟ್: ಇದು Y-ಅಕ್ಷದ ಮೇಲಿದೆ, y=5.
describe_point(Point(3, 4))  # ಔಟ್‌ಪುಟ್: ಪಾಯಿಂಟ್ (3, 4) ನಲ್ಲಿದೆ.

7. ಗಾರ್ಡ್‌ಗಳು (Guards)

ಒಂದು case ಸ್ಟೇಟ್‌ಮೆಂಟ್‌ಗೆ ಹೆಚ್ಚುವರಿ ಷರತ್ತು (condition) ಸೇರಿಸಲು if ಕ್ಲಾಸ್ ಅನ್ನು ಬಳಸಬಹುದು. ಇದನ್ನು "ಗಾರ್ಡ್" ಎನ್ನುತ್ತಾರೆ. ಪ್ಯಾಟರ್ನ್ ಮ್ಯಾಚ್ ಆದ ನಂತರವೇ ಗಾರ್ಡ್ ಅನ್ನು ಪರಿಶೀಲಿಸಲಾಗುತ್ತದೆ.

ಉದಾಹರಣೆ:

def describe_point_with_guard(p):
    match p:
        case Point(x=x, y=y) if x == y:
            print(f"ಈ ಪಾಯಿಂಟ್ y=x ರೇಖೆಯಲ್ಲಿದೆ, ({x}, {y}).")
        case Point(x=x, y=y):
            print(f"ಪಾಯಿಂಟ್ ({x}, {y}) ನಲ್ಲಿದೆ.")

describe_point_with_guard(Point(5, 5)) # ಔಟ್‌ಪುಟ್: ಈ ಪಾಯಿಂಟ್ y=x ರೇಖೆಯಲ್ಲಿದೆ, (5, 5).
describe_point_with_guard(Point(3, 4)) # ಔಟ್‌ಪುಟ್: ಪಾಯಿಂಟ್ (3, 4) ನಲ್ಲಿದೆ.
ಈ ಎಲ್ಲಾ ವೈಶಿಷ್ಟ್ಯಗಳು match-case ಅನ್ನು ಸಂಕೀರ್ಣ ಡೇಟಾ ರಚನೆಗಳನ್ನು ನಿರ್ವಹಿಸಲು ಅತ್ಯಂತ ಶಕ್ತಿಯುತ ಸಾಧನವನ್ನಾಗಿ ಮಾಡುತ್ತವೆ.