C#转Python第1.7篇:for 循环的前世今生:C# 的 foreach 在 Python 里变成了什么?
2026/5/21 21:28:27 网站建设 项目流程

在 C# 里写 for 循环,你得这样:

for (int i = 0; i < 10; i++) { Console.WriteLine(i); }

在 Python 里?这样:

for i in range(10): print(i)

发现了没?Python 的 for 循环没有i++,没有i < 10,只有一个range(10)

还有那个让 C# 程序员崩溃的for...else——循环没被 break 就执行 else?这是什么鬼?

今天咱们来聊聊循环结构——C# 的"传统 for" vs Python 的"for-in"。

for 循环

C# 版本:

// 传统 for 循环 for (int i = 0; i < 10; i++) { Console.WriteLine(i); } // foreach 循环 int[] numbers = { 1, 2, 3, 4, 5 }; foreach (var num in numbers) { Console.WriteLine(num); } // 倒序遍历 for (int i = numbers.Length - 1; i >= 0; i--) { Console.WriteLine(numbers[i]); } // 带索引的 foreach for (int i = 0; i < numbers.Length; i++) { Console.WriteLine($"{i}: {numbers[i]}"); }

Python 版本:

# for-in 循环(Python 只有这一种 for) for i in range(10): print(i) # 遍历列表 numbers = [1, 2, 3, 4, 5] for num in numbers: print(num) # 倒序遍历 for num in reversed(numbers): print(num) # 带索引的遍历 for i, num in enumerate(numbers): print(f"{i}: {num}")
对比项C#Python
传统 forfor (int i=0; i<10; i++)for i in range(10):
foreachforeach (var x in list)for x in list:
倒序for (int i=len-1; i>=0; i--)for x in reversed(list):
带索引手动维护ienumerate(list)
步长i += 2range(0, 10, 2)

Python 的 for 循环是"for-in"风格——你只需要说"遍历这个",不需要告诉它怎么走。C# 的传统 for 循环是"命令式"的,你得告诉它从哪开始、到哪结束、每次加多少。

while 循环

C# 版本:

int i = 0; while (i < 10) { Console.WriteLine(i); i++; } // do-while 循环(Python 没有) int j = 0; do { Console.WriteLine(j); j++; } while (j < 10);

Python 版本:

i = 0 while i < 10: print(i) i += 1 # Python 没有 do-while,但可以模拟 # 方法 1:while True + break while True: print(i) i += 1 if i >= 10: break # 方法 2:使用 walrus 运算符(3.8+) while (i := i + 1) <= 10: print(i)

C# 有 do-while,Python 没有。Python 的替代方案是while True + break,或者用 walrus 运算符:=

循环控制

C# 版本:

for (int i = 0; i < 100; i++) { if (i == 5) continue; // 跳过 5 if (i == 10) break; // 遇到 10 停止 Console.WriteLine(i); }

Python 版本:

for i in range(100): if i == 5: continue # 跳过 5 if i == 10: break # 遇到 10 停止 print(i)

breakcontinue的用法在两种语言里几乎一样——这是少数几个完全相同的地方。

for-else:Python 独有的"反直觉"设计

这是 Python 最让人困惑的特性之一:

# for-else 在循环正常结束时执行(没有 break) for i in range(10): if i == 5: print("找到了 5") break else: # 循环正常结束(没有 break)才执行 print("没找到 5") # 实际应用场景:搜索 def find_item(lst, target): for item in lst: if item == target: return item else: # 循环正常结束,没有 return return None

C# 没有 for-else,Python 的 for-else 在循环没有被 break 时执行 else 块。这个设计很反直觉,但用对了场景会很方便。

enumerate 和 zip

C# 的索引遍历:

string[] names = { "Alice", "Bob", "Charlie" }; for (int i = 0; i < names.Length; i++) { Console.WriteLine($"{i + 1}. {names[i]}"); } // 并行遍历 string[] names2 = { "Alice", "Bob" }; int[] ages = { 25, 30 }; for (int i = 0; i < names2.Length; i++) { Console.WriteLine($"{names2[i]}: {ages[i]}"); }

Python 的 enumerate 和 zip:

# enumerate(自动索引) names = ["Alice", "Bob", "Charlie"] for i, name in enumerate(names, start=1): print(f"{i}. {name}") # zip(并行遍历) names2 = ["Alice", "Bob"] ages = [25, 30] for name, age in zip(names2, ages): print(f"{name}: {age}") # enumerate + zip students = ["Alice", "Bob"] scores = [90, 85] for i, (name, score) in enumerate(zip(students, scores)): print(f"{i + 1}. {name}: {score}")

Python 的enumerate()zip()让你告别手动索引的痛苦。C# 得手动维护i,Python 直接解包就行。

推导式预告

Python 的列表推导式(第二阶段详细讲):

numbers = [1, 2, 3, 4, 5] # 传统 for 循环 squares = [] for x in numbers: squares.append(x ** 2) # 列表推导式 squares = [x ** 2 for x in numbers] # [1, 4, 9, 16, 25] # 带条件的推导式 even_squares = [x ** 2 for x in numbers if x % 2 == 0] # [4, 16] # 字典推导式 square_dict = {x: x ** 2 for x in numbers} # {1: 1, 2: 4, ...} # 集合推导式 square_set = {x ** 2 for x in numbers} # {1, 4, 9, 16, 25}

列表推导式是 Python 的杀手锏——一行代码顶 C# 的Select().ToList()

设计哲学

C# 的哲学是多种循环——for、foreach、while、do-while,传统风格,类型安全,LINQ 扩展。

Python 的哲学是统一风格——for x in iterable是唯一写法,迭代器协议让任何可迭代对象都能用 for,enumerate 和 zip 告别手动索引。

C# 的 for 循环是"命令式"的,你得告诉它怎么走; Python 的 for 循环是"声明式"的,你只需要说"遍历这个"。

更深层的原因

  • C# 的 for 循环需要明确的起始、终止、步长,这是C 风格的延续

  • Python 的 for 循环只需要一个可迭代对象,这是迭代器协议的体现

真实场景:在处理文件行时,Python 的 for 循环非常优雅:

# 逐行读取文件 with open("data.txt") as f: for line in f: # 直接遍历文件对象 print(line.strip())

C# 得这样写:

// 逐行读取文件 foreach (var line in File.ReadLines("data.txt")) { Console.WriteLine(line); }

Python 的for line in f直接遍历文件对象,C# 需要File.ReadLines()方法。

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

  1. 忘记 range 是左闭右开range(5)是 0-4,不是 0-5

  2. 以为 for-else 很奇怪:它是用来搜索的,找到就 break,没找到就执行 else

  3. 忘记 enumerate:Python 不需要手动维护索引

  4. 以为 zip 会以最长为准:zip 以最短为准,用zip_longest以最长为准

  5. 遍历时修改列表:Python 不允许,用推导式或遍历副本

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

坑点提醒

range 的边界——range 是左闭右开的:

for i in range(5): # 0, 1, 2, 3, 4(不包括 5) print(i) for i in range(1, 5): # 1, 2, 3, 4 print(i)

for-else 的执行条件——循环没有 break 才执行 else:

for i in range(10): if i == 5: break else: print("循环没有 break") # 这不会执行(因为 break 了)

修改列表的陷阱——遍历时不能安全修改列表:

lst = [1, 2, 3, 4, 5] # 正确做法:遍历副本或使用推导式 lst = [x for x in lst if x % 2 != 0]

zip 的长度——zip 以最短的为准:

a = [1, 2, 3] b = ['a', 'b'] print(list(zip(a, b))) # [(1, 'a'), (2, 'b')] # 如果要以最长为准,用 itertools.zip_longest from itertools import zip_longest print(list(zip_longest(a, b, fillvalue=None)))

一句话总结

Python 的for...else是个"反直觉"的设计——循环没被 break 就执行 else。

下一篇咱们来聊聊列表和数组——C# 的ArrayList在 Python 里合体了,还有那个让 C# 程序员眼红的列表推导式。


获取更多资源

📦代码仓库

  • GitHub:https://github.com/LadyKiller1025/csharp-python-demos

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

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

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

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

立即咨询