在 C# 里写条件判断,你得这样:

if (x > 0)
{
    Console.WriteLine("正数");
}
else if (x < 0)
{
    Console.WriteLine("负数");
}
else
{
    Console.WriteLine("零");
}

在 Python 里?这样:

if x > 0:
    print("正数")
elif x < 0:
    print("负数")
else:
    print("零")

发现了没?Python 的 elif 比 C# 的 else if 少打一个空格。这就是 Python 的"懒人哲学"。

今天咱们来聊聊条件判断——C# 的"大括号" vs Python 的"缩进"。

基本 if-else

C# 版本:

int x = 5;

if (x > 0)
{
    Console.WriteLine("正数");
}

if (x > 0)
{
    Console.WriteLine("正数");
}
else
{
    Console.WriteLine("非正数");
}

if (x > 0)
{
    Console.WriteLine("正数");
}
else if (x < 0)
{
    Console.WriteLine("负数");
}
else
{
    Console.WriteLine("零");
}

Python 版本:

x = 5

if x > 0:
    print("正数")

if x > 0:
    print("正数")
else:
    print("非正数")

if x > 0:
    print("正数")
elif x < 0:
    print("负数")
else:
    print("零")
对比项 C# Python
if if (condition) { } if condition:
else else { } else:
else if else if elif(Python 独有)
代码块 {} 缩进(4 空格)
条件括号 必须 可选

Python 的 elif 是一个关键字,不是两个——else if 变成了 elif,少打一个空格,这就是 Python 的"懒人哲学"。

三元表达式

C# 版本:

int x = 5;
string result = x > 0 ? "正数" : "非正数";

// C# 9+ 模式匹配
string result2 = x switch
{
    > 0 => "正数",
    < 0 => "负数",
    _ => "零"
};

Python 版本:

x = 5
result = "正数" if x > 0 else "非正数"

# Python 3.10+ match-case
match x:
    case _ if x > 0:
        result2 = "正数"
    case _ if x < 0:
        result2 = "负数"
    case _:
        result2 = "零"

# 海象运算符(3.8+)
if (n := len([1, 2, 3])) > 2:
    print(f"长度是 {n}")

C# 的三元表达式是 条件 ? 值1 : 值2,Python 的是 值1 if 条件 else 值2——顺序反过来了。

真值判断

这是 C# 程序员最容易踩的坑。

C# 版本:

string s = "hello";
int n = 0;
List<int> list = new List<int>();

if (s != null) { }      // 检查 null
if (s.Length > 0) { }   // 检查空字符串
if (n != 0) { }         // 检查非零
if (list.Count > 0) { } // 检查非空列表

Python 版本:

s = "hello"
n = 0
lst = [1, 2, 3]
empty_list = []
none_val = None

if s:        # 非空字符串为 True
    print("s 不为空")
if n:        # 0 为 False
    print("n 不为零")
if lst:      # 非空列表为 True
    print("lst 不为空")
if empty_list:  # 空列表为 False
    print("这不会执行")
if none_val:    # None 为 False
    print("这也不会执行")

# Python 的真值表
# False: None, False, 0, 0.0, "", [], {}, set(), tuple()
# True: 其他所有值
特性 C# Python
null/None x != null if x:(隐式)
空字符串 s.Length > 0 if s:(隐式)
零值 n != 0 if n:(隐式)
空集合 list.Count > 0 if lst:(隐式)

C# 得写一堆 != nullLength > 0Count > 0,Python 直接 if x: 一个搞定。但要注意——Python 的 if x: 判断逻辑和 C# 不同,空字符串、0、空列表都是 False。

模式匹配

C# 9+ 引入了强大的模式匹配:

object obj = 5;

// 类型模式
if (obj is int n)
{
    Console.WriteLine($"是整数: {n}");
}

// 属性模式
if (obj is string { Length: > 0 } s)
{
    Console.WriteLine($"非空字符串: {s}");
}

// switch 表达式
string GetCategory(int score) => score switch
{
    >= 90 => "优秀",
    >= 80 => "良好",
    >= 60 => "及格",
    _ => "不及格"
};

Python 3.10+ 也有了 match-case:

obj = 5

# 基本匹配
match obj:
    case int() as n:
        print(f"是整数: {n}")
    case str() as s if len(s) > 0:
        print(f"非空字符串: {s}")
    case _:
        print("其他类型")

# 守卫条件(guard)
match score:
    case s if s >= 90:
        category = "优秀"
    case s if 80 <= s < 90:
        category = "良好"
    case s if 60 <= s < 80:
        category = "及格"
    case _:
        category = "不及格"

Python 的 match-case 和 C# 的 switch 表达式很像,但 Python 的更灵活——支持守卫条件(guard),可以写复杂的匹配逻辑。

模式匹配进阶

序列模式(Sequence Pattern)

Python 的序列模式可以匹配列表、元组等序列:

def describe_point(point):
    match point:
        case (0, 0):
            print("原点")
        case (x, 0):
            print(f"在 x 轴上,x = {x}")
        case (0, y):
            print(f"在 y 轴上,y = {y}")
        case (x, y):
            print(f"点 ({x}, {y})")
        case _:
            print("不是二维点")

# 使用
describe_point((0, 0))   # 原点
describe_point((5, 0))   # 在 x 轴上,x = 5
describe_point((3, 4))   # 点 (3, 4)

C# 对比:

void DescribePoint((int x, int y) point) => point switch
{
    (0, 0) => Console.WriteLine("原点"),
    (var x, 0) => Console.WriteLine($"在 x 轴上,x = {x}"),
    (0, var y) => Console.WriteLine($"在 y 轴上,y = {y}"),
    (var x, var y) => Console.WriteLine($"点 ({x}, {y})"),
    _ => Console.WriteLine("不是二维点"),
};

映射模式(Mapping Pattern)

Python 独有的映射模式,可以匹配字典:

match command:
    case {"action": "quit"}:
        print("退出")
    case {"action": "move", "direction": direction}:
        print(f"向 {direction} 移动")
    case {"action": "attack", "target": target, "weapon": weapon}:
        print(f"用 {weapon} 攻击 {target}")
    case _:
        print("未知命令")

# 使用
command = {"action": "move", "direction": "north"}
match command:
    case {"action": "move", "direction": direction}:
        print(f"向 {direction} 移动")  # 输出: 向 north 移动

C# 没有直接的映射模式,需要用属性模式或 if 语句:

// C# 需要用属性模式
record Command(string Action, string? Direction, string? Target, string? Weapon);

void HandleCommand(Command cmd) => cmd switch
{
    { Action: "quit" } => Console.WriteLine("退出"),
    { Action: "move", Direction: var dir } => Console.WriteLine($"向 {dir} 移动"),
    { Action: "attack", Target: var t, Weapon: var w } => Console.WriteLine($"用 {w} 攻击 {t}"),
    _ => Console.WriteLine("未知命令"),
};

OR 模式

Python 和 C# 都支持 OR 模式,但语法不同:

# Python
match status_code:
    case 200 | 201 | 204:
        print("成功")
    case 400 | 401 | 403:
        print("客户端错误")
    case 500 | 502 | 503:
        print("服务器端错误")
    case _:
        print("其他状态码")

# 命令别名
match command:
    case "quit" | "exit" | "q":
        sys.exit()
    case "help" | "h" | "?":
        show_help()
// C#
string GetCategory(int statusCode) => statusCode switch
{
    200 or 201 or 204 => "成功",
    400 or 401 or 403 => "客户端错误",
    500 or 502 or 503 => "服务器端错误",
    _ => "其他状态码"
};

星号模式(Star Pattern)

Python 的星号模式可以匹配序列的剩余部分:

match items:
    case []:
        print("空列表")
    case [x]:
        print(f"单个元素: {x}")
    case [x, y]:
        print(f"两个元素: {x}, {y}")
    case [first, *middle, last]:
        print(f"首: {first}, 中间: {middle}, 尾: {last}")
    case [*all]:
        print(f"所有元素: {all}")

# 使用
items = [1, 2, 3, 4, 5]
match items:
    case [first, *middle, last]:
        print(f"首: {first}, 中间: {middle}, 尾: {last}")
        # 输出: 首: 1, 中间: [2, 3, 4], 尾: 5

C# 没有直接的星号模式,需要用 LINQ:

// C# 需要用 LINQ
var items = new[] { 1, 2, 3, 4, 5 };
if (items.Length >= 2)
{
    var first = items[0];
    var last = items[^1];
    var middle = items[1..^1];
    Console.WriteLine($"首: {first}, 中间: [{string.Join(", ", middle)}], 尾: {last}");
}

类模式(Class Pattern)

Python 的类模式可以匹配对象的属性:

from dataclasses import dataclass

@dataclass
class Point:
    x: int
    y: int

def describe(point):
    match point:
        case Point(x=0, y=0):
            print("原点")
        case Point(x=x, y=0):
            print(f"在 x 轴上: {x}")
        case Point(x=0, y=y):
            print(f"在 y 轴上: {y}")
        case Point(x=x, y=y):
            print(f"点 ({x}, {y})")

# 使用
describe(Point(0, 0))  # 原点
describe(Point(5, 0))  # 在 x 轴上: 5

C# 对比:

// C# 用 record 或类
record Point(int X, int Y);

string Describe(Point point) => point switch
{
    { X: 0, Y: 0 } => "原点",
    { X: var x, Y: 0 } => $"在 x 轴上: {x}",
    { X: 0, Y: var y } => $"在 y 轴上: {y}",
    { X: var x, Y: var y } => $"点 ({x}, {y})",
};

嵌套模式

Python 支持嵌套的模式匹配:

match command:
    case ("move", ("north" | "south" | "east" | "west") as direction):
        print(f"向 {direction} 移动")
    case ("attack", {"target": target, "weapon": weapon}):
        print(f"用 {weapon} 攻击 {target}")
    case _:
        print("未知命令")

# 使用
command = ("move", "north")
match command:
    case ("move", ("north" | "south" | "east" | "west") as direction):
        print(f"向 {direction} 移动")  # 输出: 向 north 移动

综合对比表

特性 C# Python
类型模式 obj is int n case int() as n:
值模式 case 42: case 42:
关系模式 > 0, < 10 守卫条件 if x > 0
属性模式 { Length: > 0 } 不支持(需守卫条件)
列表/元组模式 元组解构 (a, b) case [a, b]:
字典模式 不支持 case {"key": val}:
OR 模式 case 1 or 2: case 1 | 2:
求反模式 not null case None:
switch 表达式 x switch { ... } match x: case ...
守卫条件 when x > 0 case _ if x > 0:
弃元 _ _
嵌套解构 支持 支持
范围匹配 >= 0 and <= 100 case _ if 0 <= x <= 100:

条件表达式的"骚操作"

Python 独有的条件表达式技巧:

# 1. and/or 短路求值
x = None
value = x or "default"  # 如果 x 为 None,用 "default"

# 2. 条件赋值
result = "正数" if x > 0 else "非正数"

# 3. 多条件链式
if 0 < x < 100 and x != 50:
    print("满足条件")

# 4. 列表推导式中的条件
numbers = [1, 2, 3, 4, 5]
even = [x for x in numbers if x % 2 == 0]  # [2, 4]

# 5. any() 和 all()
numbers = [1, 2, 3, 4, 5]
has_even = any(x % 2 == 0 for x in numbers)  # True
all_positive = all(x > 0 for x in numbers)   # True

Python 的 and/or 不仅能做逻辑运算,还能用来做默认值处理——x or "default" 比 C# 的 x ?? "default" 更简洁。

设计哲学

C# 的哲学是显式结构——大括号明确代码块边界,条件表达式必须是布尔类型,模式匹配功能强大。

Python 的哲学是缩进即结构——缩进就是代码块的边界,鸭子类型让任何对象都可以作为条件,elifelse if 更简洁。

C# 像是给你一个明确的"框架",你得在框架里填内容; Python 像是给你一张白纸,你用缩进来画出结构。

更深层的原因

  • C# 的条件表达式必须返回布尔类型,这是类型安全的体现

  • Python 的条件表达式可以是任何对象,这是鸭子类型的体现——只要"看起来像布尔"就行

真实场景:在处理 API 响应时,Python 的真值判断非常方便:

# 检查响应是否成功
response = requests.get("https://api.example.com")
if response:  # 状态码 200-399 为 True
    data = response.json()
else:
    print(f"请求失败: {response.status_code}")

C# 得这样写:

var response = await httpClient.GetAsync("https://api.example.com");
if (response.IsSuccessStatusCode)
{
    var data = await response.Content.ReadAsStringAsync();
}
else
{
    Console.WriteLine($"请求失败: {response.StatusCode}");
}

迁移指南:C# 开发者最容易犯的错

  1. 忘记 elif 是一个关键字:不是 else if,是 elif

  2. 以为 if x: 只检查 None:空字符串、0、空列表都是 False

  3. 过度嵌套条件:Python 支持链式比较 0 < x < 10

  4. 忘记 and/or 返回实际值:不一定是布尔值

  5. 以为 Python 没有模式匹配:Python 3.10+ 有 match-case

推荐工具:用 VS Code + Python 插件,它会帮你检查条件表达式的常见错误。

坑点提醒

elif 不是 else if——Python 的 elif 是一个关键字:

if x > 0:
    print("正数")
elif x < 0:  # 不是 else if
    print("负数")
else:
    print("零")

条件表达式的优先级——不要嵌套太多层:

# 不要这样写(可读性差)
result = "正数" if x > 0 else "负数" if x < 0 else "零"

真值判断的陷阱——空值、零值都是 False:

if 0:        # False
    print("0 是 True")
if "":       # False
    print("空字符串是 True")
if []:       # False
    print("空列表是 True")
if None:     # False
    print("None 是 True")

一句话总结

Python 的 elif 比 C# 的 else if 少打一个空格,这就是 Python 的"懒人哲学"。

下一篇咱们来聊聊循环结构——Python 的 for...else 是个"反直觉"的设计,循环没被 break 就执行 else。


📦 代码仓库

💬 欢迎点赞、收藏、转发,你的支持是我持续创作的动力!

更多推荐