C#转Python第1.7篇:for 循环的前世今生:C# 的 foreach 在 Python 里变成了什么? 在 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 i0; i10; i)for i in range(10):foreachforeach (var x in list)for x in list:倒序for (int ilen-1; i0; 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但可以模拟 # 方法 1while 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-whilePython 没有。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)break和continue的用法在两种语言里几乎一样——这是少数几个完全相同的地方。for-elsePython 独有的反直觉设计这是 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 NoneC# 没有 for-elsePython 的 for-else 在循环没有被 break 时执行 else 块。这个设计很反直觉但用对了场景会很方便。enumerate 和 zipC# 的索引遍历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, start1): 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# 得手动维护iPython 直接解包就行。推导式预告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是唯一写法迭代器协议让任何可迭代对象都能用 forenumerate 和 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# 开发者最容易犯的错忘记 range 是左闭右开range(5)是 0-4不是 0-5以为 for-else 很奇怪它是用来搜索的找到就 break没找到就执行 else忘记 enumeratePython 不需要手动维护索引以为 zip 会以最长为准zip 以最短为准用zip_longest以最长为准遍历时修改列表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 才执行 elsefor 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, fillvalueNone)))一句话总结Python 的for...else是个反直觉的设计——循环没被 break 就执行 else。下一篇咱们来聊聊列表和数组——C# 的Array和List在 Python 里合体了还有那个让 C# 程序员眼红的列表推导式。获取更多资源代码仓库GitHubhttps://github.com/LadyKiller1025/csharp-python-demosGiteehttps://gitee.com/qakjhzx/csharp-python-demos 欢迎点赞、收藏、转发你的支持是我持续创作的动力