python 我不理解for循环中break语句的行为

8iwquhpp  于 2023-04-10  发布在  Python
关注(0)|答案(2)|浏览(163)

我正在编写一个Python练习任务,想知道我的代码的行为。我是一个C和C++程序员,完全迷失在这里。有人能告诉我为什么Python在这里做什么吗?
这段代码读取了一个以年为单位的名字表,美国各州和计数,一个孩子以它命名的频率。它基本上是来自美国的一个名字统计。下面的代码执行correkt:

with open("../data/names.csv") as file:
    file.readline() #removes table header
    counter = 0
    splitLine = {}

    for year in file:        
        splitLine = year.strip().split(',')
        
        if int(splitLine[2]) < 1950:
            continue
        if splitLine[1] != "Max":
            continue
        if splitLine[3] != "M":
            continue
        if splitLine[4] != "CA":
            continue
        if int(splitLine[2]) > 2000:
            break
            
        counter += int(splitLine[5])
        print(splitLine)

print(counter)

这段代码产生以下输出(我缩短了输出):
(...)
['663639',' Max','1998',' M','CA','285']
['666069',' Max','1999',' M','CA','296']
['668521',' Max','2000',' M','CA','341']
6385
然后我试着清理我的代码,并移动了带有break,up的if语句:

with open("../data/names.csv") as file:
    file.readline() #removes table header
    counter = 0
    splitLine = {}

    for year in file:        
        splitLine = year.strip().split(',')
        
        if int(splitLine[2]) < 1950:
            continue
        if int(splitLine[2]) > 2000:
            break
        if splitLine[1] != "Max":
            continue
        if splitLine[3] != "M":
            continue
        if splitLine[4] != "CA":
            continue
        
        counter += int(splitLine[5])
        print(splitLine)

print(counter)

此代码生成以下输出:
0
在这种情况下,for-loot似乎执行了相同的迭代,但没有到达increment-和print-语句。为什么会这样?C代码在这两种情况下的执行方式完全相同。

mklgxw1f

mklgxw1f1#

这不是语言造成的,而是你的数据排序造成的

if int(splitLine[2]) < 1950:
    continue
if int(splitLine[2]) > 2000:
    break;
if splitLine[1] != "Max":
    continue
if splitLine[3] != "M":
    continue
if splitLine[4] != "CA":
    continue

一旦它看到一个〉2000的数据,循环就会完全结束。
仔细看看你的数据。我敢打赌你会发现在你的表的 * 上半部分 *,值与

  • 年份〉2000
  • 但没有“Max”“M”和“CA”的满堂红

你的第一个程序不会在这些行上终止,因为它们没有Max/M/CA的满堂彩(因此这些行将导致continue发生)。
您的 * 第二个 * 程序将首先测试一年,并将在它遇到其中一行时立即终止。

一般来说,这是一个糟糕的过滤设计

这是因为你看到的问题:你创造了一个过滤系统,这是 * 很难推理 *。
最好像这样编写测试:

if (
    int(splitLine[2]) >= 1950 and
    int(splitLine[2]) <= 2000 and
    splitLine[1] == "Max" and
    splitLine[3] == "M" and
    splitLine[4] == "CA"
):
    counter += int(splitLine[5])
    print(splitLine)

这种安排的优点

  • 更易于阅读(因此更易于调试)
  • 矮一点但不丑
  • 您甚至可以将两个日期条件缩短为1950<=splitLine[2]<=2000

缺点

因为你不会在到达Max/M/CA的2000年时立即终止循环,所以你将搜索输入的 * 整个 *,而不是(平均而言)输入的 * 一半 *(假设你的Max/M/CA搜索条件可能是输入中的任何位置)。
然而,与您因对搜索的工作方式不自信而保存的头痛相比,这种近似两倍的搜索时间是微不足道的。

ycl3bljg

ycl3bljg2#

break语句只是退出循环。下面是一个break按预期工作的简单例子。

for i in range(0, 4):
    if i == 2:
        break
    else:
        print(i)
print(f"Loop ended with i = {i}")

输出:

相关问题