可以重复循环的某次迭代吗?
我定义了一个循环,这个循环会扫描一个由两列组成的文件。当它找到关键词 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 个回答
我不太确定你想要什么,但你能不能把标题放在一个列表里呢?
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
这段话是不是有点符合你的思路呢?
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
。
如果我理解你的问题描述没错的话,你想在某些情况下重复执行循环的主体,而不是“迭代”。如果是这样,一个可行的方法是把循环的主体做成一个可能会递归调用的函数,这个函数会返回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
就可以再次变成内联代码)。
不过,我想你发布这个问题是有原因的,也就是说,这种简单的行为(而且可以更简单地实现)对你来说并不理想——也许通过看到你字面上的问题的解决方案,你可以指出你想要的不同之处,然后我们就能真正帮助你;-)。