# 在 Python 中模拟 switch 语句的 fall-through 行为

## 什么是 fall-through

在 JavaScript 中，`switch` 语句允许 fall-through 行为。当在 `switch` 语句中发现匹配条件时，相应的代码块将被执行，直到遇到 `break` 语句，此时 `switch` 语句将退出。如果没有提供 `break` 语句，程序将继续执行下一个 `case`，而不管它是否与条件匹配。这就是所谓的 fall-through 行为。

```javascript
switch (Animal) {
    case "Dog":
    case "Cow":
        console.log("This animal is friend of people.");
    case "Giraffe":
    case "Pig":
        console.log("This animal is not extinct.");
        break;
    case "Dinosaur":
    default:
        console.log("This animal is extinct.");
}
```

## fall-through 何时有用

在多个 cases 共享同一代码块或需要跨多个 cases 执行一连串操作时，`switch` 语句中的 fall-through 会非常有用。以下是一些例子：

1. 将多个 cases 组合在一起： 当多个 cases 需要执行相同的代码块时，fall-through 可让您一个接一个地列出这些 cases，而无需重复每个 case 的代码块。这可以使代码更简洁，更易于维护。
    
    ```javascript
     switch (dayOfWeek) {
         case "Saturday":
         case "Sunday":
             console.log("It's the weekend!");
             break;
         default:
             console.log("Looking forward to the Weekend");
     }
    ```
    
2. 不同 cases 下的顺序操作： 在需要执行一系列操作的情况下，如果这些操作是建立在彼此基础之上的，但只是针对不同的情况从序列中的不同点开始执行，那么 fall-through 可以让您在不重复代码的情况下对这些操作进行结构化处理。
    
    ```javascript
     switch (userLevel) {
         case "beginner":
             beginnerTasks();
             // Fall through to execute intermediate tasks as well.
         case "intermediate":
             intermediateTasks();
             // Fall through to execute advanced tasks as well.
         case "advanced":
             advancedTasks();
             break;
     }
    ```
    
3. 设置特定条件下默认值： 您可以使用 fall-through 功能为某些情况设置默认值，然后在后面的特定情况中覆盖这些默认值。
    
    ```javascript
     switch (productType) {
         case "book":
             basePrice = 5;
             break;
         case "video":
         case "software":
             // These types have a base price and additional licensing fee.
             basePrice = 20;
             // Fall through to add licensing fee.
         default:
             licensingFee = 10;
     }
    ```
    
4. 复杂的条件逻辑：当触发一个案例的逻辑比较复杂，涉及多个步骤或条件，并且这些步骤或条件相互依存时，可以使用 fall-through 功能以可读和高效的方式来构建这一逻辑。
    
    ```javascript
     switch (true) {
         case (score >= 90):
             grade = "A";
             break;
         case (score >= 80):
             // Fall through to check for specific conditions within this range.
         case (score >= 70 && extraCredit):
             grade = "B";
             break;
         default:
             grade = "C";
     }
    ```
    

这些示例演示了在多个 cases 共享逻辑或需要跨 case 执行一系列操作的情况下，如何利用fall-through 来编写更高效、可读性和可维护性更强的代码。

## Python 的模式匹配

Python 3.10 引入了一个名为 `match-case` 语句的新特性，也称为模式匹配。该特性为处理条件逻辑提供了一种更具表现力的方式，类似于其他语言（如 JavaScript 或 C++）中的 `switch` 语句。

> 然而，与 `switch` 语句不同的是，在 Python 的 `match-case` 语句中，cases 之间没有 "fall-through"。

下面是一个如何在 Python 中使用 `match-case` 语句的示例：

```python
status = 404  # replace with the actual status
match status:
    case 400:
        result = "Bad request"
    case 404:
        result = "Not found"
    case 418:
        result = "I'm a teapot"
    case _:
        result = "Unknown status"
print(result)
```

在这个示例中，`match` 关键字后面是要匹配的表达式 (`status`)，`case` 后面是要匹配的模式。最后一个 `case` 语句中的 `_` 是一个通配符，可以匹配任何内容，类似于 `switch` 语句中的 `default` case。

您还可以使用更复杂的模式，并在模式中添加 guard 子句。guard 是一个 `if` 子句，它进一步细化了 case 的条件。如果 guard 为 false，则 `match` 会继续尝试下一个 case 块。

```python
point = (1, 1)  # replace with the actual point
match point:
    case (x, y) if x == y:
        # the case statement matches a tuple and 
        # uses a guard to check if the two elements of the tuple are equal.
        print(f"The point is located on the diagonal Y=X at {x}.")
    case (x, 0):
        print(f"X={x} and the point is on the x-axis.")
    case (0, y):
        print(f"Y={y} and the point is on the y-axis.")
    case (0, 0):
        print("The point is at the origin.")
    case (x, y) if x > 0 and y > 0:
        print(f"The point is in the first quadrant at ({x}, {y}).")
    case _:
        print(f"Point is not on the diagonal or axes at ({x}, {y}).")
```

## 如何在 Python 中模拟 switch 的 fall-through

### 不使用 fall-through

```python
if user_level == "beginner":
    beginnerTasks()
    intermediateTasks()
    advancedTasks()
elif user_level == "intermediate":
    intermediateTasks()
    advancedTasks()
elif user_level == "advanced":
    advancedTasks()
```

### 模拟 fall-through

在 Python 中，您可以使用一系列 `if` 语句和一个标志变量来模拟 `switch` 语句的 fall-through 行为。以下代码可供参考：

```python
fall_through = False

if user_level == "beginner":
    beginnerTasks()
    fall_through = True
if fall_through or user_level == "intermediate":
    intermediateTasks()
    fall_through = True
if fall_through or user_level == "advanced":
    advancedTasks()
```

在这段代码中，`fall_through` 变量用于控制是否执行后续 `if` 语句中的代码。如果 `user_level` 为 "beginner"，则调用 `beginnerTasks()`，并将 `fall_through` 设为 `True`。这将导致执行下一个 `if` 语句中的代码，而不验证 `user_level` 的值。同样的逻辑也适用于 "intermediate" 级别。如果 `user_level` 是 "advanced"，那么只有 `advancedTasks()` 被调用，因为 `fall_through` 在开始时是 `False`。

## Python 的 match-case 语句的优点

在支持 fall-through 的语言（如 C 或 JavaScript）中，它的风险在于，如果程序员忘记在每个 `case` 的结尾加入 `break` 语句，就可能导致错误。如果没有 `break`，程序将继续执行下一个 `case` 的代码，这可能不是预期的行为，会导致意想不到的结果。

Python 3.10 引入的 `match-case` 语句的优点包括：

1. 无跳转： Python 的 `match-case` 没有 fall-through 行为，这消除了意外执行多个 cases 的风险。一旦发现匹配，Python 会执行相应 case 块中的语句，然后跳到 `match` 块的末尾，继续执行程序的其余部分。
    
2. 模式匹配：`match-case` 语句是为模式匹配而设计的，它比简单的值匹配更强大。它允许匹配类型模式，而不仅仅是值，这可以使代码更具表现力和可读性。
    
3. 复杂匹配： Python 的 `match-case` 可以处理复杂的匹配，并且可以在单个 `case` 块中处理多种可能的情况，这可以简化逻辑并减少嵌套 `if` 语句的需要。
    
4. 可读性： `match-case` 语句提供了一种结构清晰的方式来处理多个条件，从而使代码更具可读性，这通常比一长串 `if-elif-else` 语句更优雅。
    
5. 多重模式： 您可以使用 `|` 操作符在单例中匹配多个模式，从而以简洁的方式处理多个相关条件，而无需重复代码。
    
6. 默认情况：`match-case` 语句中的默认情况用下划线 `_` 表示，它可以捕获前面 cases 中没有匹配到的任何值，确保涵盖所有可能性。
    

总之，Python 的 `match-case` 语句为传统 fall-through 行为的 `switch` 语句提供了一个更安全、更强大的替代方案，减少了 bug 的风险，提高了代码的清晰度。
