可以重复循环的某次迭代吗?

1 投票
3 回答
3664 浏览
提问于 2025-04-16 01:13

我定义了一个循环,这个循环会扫描一个由两列组成的文件。当它找到关键词 DEFINE_MENU 时,这一行的第二列就代表一个屏幕的标题。接下来出现的关键词会定义另一个屏幕的标题,依此类推,直到第n个屏幕。目前这段代码只能定义第一个菜单标题。

我想知道,当我到达第二次出现的关键词 DEFINE_MENU 时,是否可以重复这个循环,保持在同一行,设置 title_flag = 0,这样就能捕捉到第二个菜单标题?

def getInfo():

    title_flag = 0
    number = 1
    menus = {}
    items = {}
    title = None
    file = open('some_file', 'r')
    for line in file:
        # Test for comments, if they exist pass and move on
        if line[0] == '#':
            continue
        # Hop over blank lines
        if re.search(r'^\s+$', line):
            continue
        # Find the line where the title is defined
        if re.search('DEFINE_MENU', line) and title_flag == 0:
            type, name = line.split()
            title = name
            title_flag = 1
            continue
        # If DEFINE_MENU is found and flag has been raised, this
        # signifies a new menu definition so break.
        if re.search('DEFINE_MENU', line) and title_flag == 1:
            break
        if re.search('PRIV', line):
            (type, name, priv_holder, *description) = line.split()
        else:
            (type, name, *description) = line.split()
        # If flag has been raised, the line must follow the definition
        # of the menu, it must contains info regarding a menu item.
        if title_flag == 1:
            description = ' '.join(description)
            items[str(number)] = name
            number += 1
    file.close()
    menus[title] = items
    return menus

谢谢你的建议!

汤姆

编辑: 首先,对造成的困惑表示歉意。也许我把问题想得太简单了,提供的信息也不够。我会深入探讨一下,我使用的输入文件格式如下:

# MENU TYPE     NAME            PRIV?   DESCRIPTION
DEFINE_MENU     CRAGINS
MENU            menu_name1              This takes you to menu 1
MENU            menu_name2              This takes you to menu 2
VARIABLE        var_name1               Alter variable1
VARIABLE        var_name2       PRIV    Alter variable1
COMMAND         command1                Perform command1
DEFINE_MENU     MENU2
MENU            menu_name3              This takes you to menu 3
MENU            menu_name4              This takes you to menu 4
VARIABLE        var_name3               Alter variable3
VARIABLE        var_name4       PRIV    Alter variable4
COMMAND         command3                Perform command3

我在 DEFINE_MENU 调用之间设置了一个标志,以便进一步处理数据。我已经编辑了代码,包含了我写的完整方法。

目前的结果是一个字典,其中键是菜单标题,值是另一个字典,包含菜单项(标题后面的值),如下所示:

{'title1': {'1': 'menu_name1', '3': 'var_name1', '2': 'menu_name2', '5': 'command1', '4': 'var_name2'}}

我希望得到一个更大的字典,包含菜单标题作为键,最底层的字典作为值。我知道这有点复杂,如果不清楚请告诉我,我会提供更多信息。

再次感谢

汤姆

3 个回答

0

我不太确定你想要什么,但你能不能把标题放在一个列表里呢?

titles = []

for line in infile: # don't shadow "file" keyword...

    if "DEFINE_MENU" in line:
        titles.append(line.split()[-1]) # append the last item

如果你只想要前两个标题,你可以加一个额外的判断:

if len(titles) == 2: break
0

这段话是不是有点符合你的思路呢?

menus = []
current_menu = None
for line in file:
    # ...
    # Find the line where the title is defined
    if re.search('DEFINE_MENU', line):
        if not current_menu is None:
            menus.append(current_menu)
        current_menu = Menu()
        type, name = line.split()
        current_menu.setTitle(name)
        continue

Menu 是一个辅助类,用来存储属于一个菜单的所有信息。而且,因为你提到的所有情况似乎是互不相同的,建议你用 elif 来替代 continue

2

如果我理解你的问题描述没错的话,你想在某些情况下重复执行循环的主体,而不是“迭代”。如果是这样,一个可行的方法是把循环的主体做成一个可能会递归调用的函数,这个函数会返回True表示要退出循环,返回False表示要继续执行,同时还可以返回可能的标题。例如,一个最直接的(虽然可能不是最优雅的)函数:

def body(line):
    global title_flag

    # skip over comments
    if line[0] == '#':
        return None, False
    # skip over blank lines
    if re.search(r'^\s+$', line):
        return None, False

    # Find the line where the title is defined
    if 'DEFINE_MENU' in line and title_flag == 0:
        type, name = line.split()
        title = name
        title_flag = 1
        return title, body(line)

    # If DEFINE_MENU is found and flag has been raised, this
    # signifies a new menu definition.
    if 'DEFINE_MENU' in line and title_flag == 1:
        return None, True

然后主代码就变成:

title_flag = 0

with open('some_file', 'r') as afile:
    for line in afile:
        thetitle, mustbreak = body(line)
        if thetitle is not Note: title = thetitle
        if mustbreak: break

顺便说一句,千万不要用内置的名字来命名你自己的变量,比如file——这是另一个话题;-)。另外,我使用with(假设你用的是Python 2.6或更高版本,或者是2.5加上“从未来导入”)只是因为这是打开和关闭文件的正确方式;-)。还有,我去掉了re.search,因为用简单的in操作符就能完成同样的工作,使用re.search实在是多此一举。

我发布这段代码主要是想具体检查一下我是否理解了你的需求,因为从行为上看,这确实有些过于复杂——根据你发布的代码,没有必要重复检查注释和空行,也没有必要再搜索'DEFINE_MENU'等等……你可以在设置好标题后直接退出(这样body就可以再次变成内联代码)。

不过,我想你发布这个问题是有原因的,也就是说,这种简单的行为(而且可以更简单地实现)对你来说并不理想——也许通过看到你字面上的问题的解决方案,你可以指出你想要的不同之处,然后我们就能真正帮助你;-)。

撰写回答