C#转Python第2.3篇:上周帮同事 review 代码,他一行 Python 让我愣了 5 秒
2026/7/24 22:37:02 网站建设 项目流程

C#转Python第2.3篇:上周帮同事 review 代码,他一行 Python 让我愣了 5 秒

上周帮同事 review 代码,他甩过来一行 Python:[x * 2 for x in nums if x > 0]。我愣了 5 秒——这不就是我用 LINQ 写了三年的Where().Select()吗?一行顶三行,Python 玩家果然任性。

不过等我看到后面的需求——分组、聚合、延迟执行——我又默默打开了 C# 的 LINQ。两种写法各有各的杀手锏,C# 的 LINQ 像是"流水线",Python 的推导式像是"压缩包"。

基础语法对比

C# 版本:

var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // 筛选 var evens = numbers.Where(x => x % 2 == 0).ToList(); // 转换 var doubled = numbers.Select(x => x * 2).ToList(); // 排序 var sorted = numbers.OrderByDescending(x => x).ToList(); // 聚合 var sum = numbers.Sum(); var avg = numbers.Average(); // 链式调用 var result = numbers .Where(x => x > 3) .Select(x => x * 2) .OrderBy(x => x) .ToList(); // C# 12 集合表达式(更简洁) int[] nums = [1, 2, 3, 4, 5]; List<int> list = [1, 2, 3, 4, 5]; IEnumerable<int> more = [.. nums, 6, 7, 8]; // 展开运算符

Python 版本:

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # 筛选 evens = [x for x in numbers if x % 2 == 0] # 转换 doubled = [x * 2 for x in numbers] # 排序 sorted_list = sorted(numbers, reverse=True) # 聚合 total = sum(numbers) avg = sum(numbers) / len(numbers) # 链式操作 result = [x * 2 for x in numbers if x > 3] result = sorted([x * 2 for x in numbers if x > 3])

对比一下:

操作C# LINQPython 列表推导式
筛选list.Where(x => x > 0)[x for x in list if x > 0]
转换list.Select(x => x * 2)[x * 2 for x in list]
排序list.OrderBy(x => x)sorted(list)
聚合list.Sum()sum(list)
链式.Where().Select().ToList()[... for x in list if ...]

C# 的 LINQ 是"方法链",Python 的推导式是"表达式压缩"。

复杂操作对比

多条件筛选

C# 版本:

var users = GetUsers(); // 多条件筛选 var result = users .Where(u => u.Age >= 18) .Where(u => u.IsActive) .Where(u => u.Score > 80) .ToList(); // 或者用 && 连接 var result2 = users .Where(u => u.Age >= 18 && u.IsActive && u.Score > 80) .ToList();

Python 版本:

users = get_users() # 多条件筛选 result = [u for u in users if u["age"] >= 18 and u["is_active"] and u["score"] > 80] # 或者分行写 result = [ u for u in users if u["age"] >= 18 and u["is_active"] and u["score"] > 80 ]

嵌套循环

C# 版本:

// 笛卡尔积 var colors = new[] { "红", "蓝", "绿" }; var sizes = new[] { "S", "M", "L" }; var combinations = colors .SelectMany(c => sizes, (c, s) => new { Color = c, Size = s }) .ToList(); // 或者用嵌套 Select var combinations2 = colors .SelectMany(c => sizes.Select(s => new { Color = c, Size = s })) .ToList();

Python 版本:

# 笛卡尔积 colors = ["红", "蓝", "绿"] sizes = ["S", "M", "L"] combinations = [(c, s) for c in colors for s in sizes] # 等价于 combinations = [] for c in colors: for s in sizes: combinations.append((c, s))

Python 的嵌套循环更直观,C# 需要SelectMany

字典推导

C# 版本:

var users = new List<User> { /* ... */ }; // 转换为字典 var userDict = users.ToDictionary(u => u.Id, u => u.Name); // 用 LINQ 生成字典 var priceDict = products .Where(p => p.IsActive) .ToDictionary(p => p.Id, p => p.Price);

Python 版本:

users = [{"id": 1, "name": "张三"}, ...] # 字典推导 user_dict = {u["id"]: u["name"] for u in users} # 带条件的字典推导 price_dict = { p["id"]: p["price"] for p in products if p["is_active"] }

集合推导

C# 版本:

var numbers = new List<int> { 1, 2, 2, 3, 3, 3, 4 }; // 用 HashSet 去重 var unique = new HashSet<int>(numbers); // 用 LINQ Distinct var distinct = numbers.Distinct().ToList();

Python 版本:

numbers = [1, 2, 2, 3, 3, 3, 4] # 集合推导(自动去重) unique = {x for x in numbers} # {1, 2, 3, 4} # 列表去重(保持顺序) distinct = list(dict.fromkeys(numbers)) # [1, 2, 3, 4]

性能对比

C# 版本:

// LINQ 延迟执行 var query = numbers.Where(x => x > 0); // 不会立即执行 var result = query.ToList(); // 这里才执行 // 可以利用延迟执行优化 var result = numbers .Where(x => x > 0) // 延迟 .Select(x => x * 2) // 延迟 .Take(10) // 延迟 .ToList(); // 执行,只处理前 10 个

Python 版本:

# 列表推导式立即执行 result = [x * 2 for x in numbers if x > 0] # 立即创建整个列表 # 生成器表达式延迟执行 result = (x * 2 for x in numbers if x > 0) # 不会立即创建列表 # 用 next() 取第一个 first = next(x * 2 for x in numbers if x > 0) # 或者用生成器配合函数 result = list(islice( (x * 2 for x in numbers if x > 0), 10 ))

C# 的 LINQ 天然支持延迟执行,Python 需要用生成器表达式。

可读性对比

C# 版本:

// 复杂的链式调用 var result = orders .Where(o => o.Status == OrderStatus.Completed) .Where(o => o.OrderDate >= DateTime.Now.AddDays(-30)) .SelectMany(o => o.Items) .GroupBy(i => i.ProductId) .Select(g => new { ProductId = g.Key, TotalQuantity = g.Sum(i => i.Quantity), TotalAmount = g.Sum(i => i.Quantity * i.Price) }) .OrderByDescending(x => x.TotalAmount) .Take(10) .ToList();

Python 版本:

# 等价的 Python 写法 result = [ { "product_id": product_id, "total_quantity": sum(i["quantity"] for i in items), "total_amount": sum(i["quantity"] * i["price"] for i in items) } for product_id, items in groupby( [ i for o in orders if o["status"] == "completed" and o["order_date"] >= datetime.now() - timedelta(days=30) for i in o["items"] ], key=lambda i: i["product_id"] ) ] # 或者用 Pandas(更清晰) import pandas as pd df = pd.DataFrame(orders) result = ( df[df["status"] == "completed"] .query("order_date >= @thirty_days_ago") .explode("items") .groupby("product_id") .agg({"quantity": "sum", "amount": "sum"}) .nlargest(10, "amount") )

C# 的 LINQ 链更清晰,Python 的复杂推导式可读性较差。

设计哲学

C# 的 LINQ 是"方法链模式"——每个操作返回新的序列,可以链式调用,适合复杂的数据处理管道。

Python 的推导式是"表达式压缩"——用一行代码表达复杂的逻辑,适合简单的转换和筛选。

C# 的 LINQ 像是"流水线",每个环节清晰可见; Python 的推导式像是"压缩包",解压后才能看清内部。

坑点提醒

Python 推导式的变量泄漏——变量会泄漏到外部作用域:

x = 10 result = [x for x in range(5)] print(x) # 4!不是 10 了 # 避免方法:Python 3.0+ 的推导式有自己的作用域 # 但在旧版本中,推导式变量会泄漏

过度嵌套的推导式——可读性灾难:

# 不好:嵌套太深 result = [ f(x, y) for x in range(10) for y in range(10) if g(x, y) for f in [h1, h2, h3] if condition(f, x, y) ] # 好:拆分成多步 filtered = [(x, y) for x in range(10) for y in range(10) if g(x, y)] result = [f(x, y) for x, y in filtered for f in [h1, h2, h3] if condition(f, x, y)]

C# 的 LINQ 方法命名——英语不好会很痛苦:

// 需要记住很多方法名 // Where, Select, SelectMany, OrderBy, ThenBy // GroupBy, Distinct, Except, Intersect, Union // Any, All, First, Last, Single // Sum, Average, Min, Max, Count // Python 的关键字更直观 # for, in, if, sorted, sum, len

性能陷阱——不必要的转换:

// 不好:多次转换 var result = list.Where(x => x > 0).Select(x => x * 2).ToList(); // 好:一次转换 var result = list.Where(x => x > 0).Select(x => x * 2).ToList(); // 上面两个一样,但注意不要在循环中多次调用 ToList()
# 不好:多次创建列表 result1 = [x for x in numbers if x > 0] result2 = [x * 2 for x in result1] # 好:一次完成 result = [x * 2 for x in numbers if x > 0]

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

  1. 混淆推导式和生成器表达式[x for x in list]立即创建列表,(x for x in list)是生成器

  2. 忘记推导式变量泄漏:Python 3.12 之前,推导式变量会泄漏到外部作用域

  3. 过度使用推导式:复杂逻辑应该用普通循环,可读性更重要

  4. **用sorted()代替.OrderBy()**:sorted()返回新列表,原列表不变

  5. **用sum()/len()代替.Average()**:Python 没有内置的average()函数

  6. **用in代替.Contains()**:"x" in listlist.__contains__("x")更 Pythonic

一句话总结

C# 的 LINQ 是"流水线",Python 的推导式是"压缩包"——都能处理集合,但风格完全不同。

下一篇咱们来聊聊生成器与迭代器——C# 的yield return和 Python 的yield,几乎一样的设计哲学!


📦示例代码:C# 转 Python 全系列配套练习代码(含 48 章示例)

  • GitHub:GitHub - LadyKiller1025/csharp-python-demos: C# vs Python 学习系列 - Demo 代码合集 · GitHub

  • Gitee:https://gitee.com/qakjhzx/csharp-python-demos

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询