当我阅读关于finding all cycles in graph implementation的另一个讨论主题时,我遇到了这个问题。任何人都可以在这个例子中解释这对关键字的用法吗?感谢。
01 def dfs(graph, start, end):
02 fringe = [(start, [])]
03 while fringe:
04 state, path = fringe.pop()
05 if path and state == end:
06 yield path
07 continue
08 for next_state in graph[state]:
09 if next_state in path:
10 continue
11 fringe.append((next_state, path+[next_state]))
>>> graph = { 1: [2, 3, 5], 2: [1], 3: [1], 4: [2], 5: [2] }
>>> cycles = [[node]+path for node in graph for path in dfs(graph, node, node)]
>>> len(cycles)
7
>>> cycles
[[1, 5, 2, 1], [1, 3, 1], [1, 2, 1], [2, 1, 5, 2], [2, 1, 2], [3, 1, 3], [5, 2, 1, 5]]
答案 0 :(得分:1)
这两个关键词没有密切关系。
continue
关键字只能出现在循环体(for
或while
语句)中,并导致控制流返回循环顶部继续通过循环体的其余部分。它通常是在if
或else
块中缩进循环体的其余部分的替代方法。这样:
while foo():
if something():
continue
bar()
baz()
完全相同:
while foo():
if not something():
bar()
baz() # but note that these lines are more indented in this version!
与continue
密切相关的另一个关键字是break
,这会导致控制流立即退出循环,而不是返回到顶部。 continue
和break
都只能影响最接近的循环,所以如果你有嵌套的控制结构,很难一次性将它们全部中断(或continue
外部循环在内心里面。)
yield
关键字非常不同。虽然它经常出现在循环中,但并不是必须的。相反,它只允许在函数体内。它将功能更改为“生成器功能”。当调用生成器函数时,其代码不会立即运行,而是创建“生成器对象”并将其返回给调用者。生成器对象是一种迭代器,可以通过for
循环(或通过调用next()
手动)进行迭代。只有在迭代生成器对象时,函数的代码才会运行。每次到达yield
语句时,函数的执行暂停,并且如果没有指定值,则产生的值(或None
)将作为迭代的值给出。 (请注意,当有人随意调用某个“生成器”时,它们可能意味着生成器函数或生成器对象。通常清楚它们来自上下文。)
以下是一些使用生成器打印1
,2
和3
的示例代码:
def generator_function():
yield 1 # because it contains `yield` statements, this is a generator function
yield 2
yield 3
generator_object = generator_function() # you can create a variable for the generator object
for value in generator_object: # but often you'd create it on the same line as the loop
print(value)
另一个与yield
有些相似的关键字是return
,这只在函数中有意义。它立即结束函数的执行以返回指定的值(如果没有指定值,则为None
。)
您展示的dfs
功能会依次使用yield
和continue
。这样做首先产生一个值(在请求下一个值之前停止生成器函数的执行),然后一旦执行恢复,它就会回到循环的开始。
如果你想,你可以重写函数以避免其中任何一个(虽然结果函数会有所不同,因为它不再是一个惰性生成器):
def dfs(graph, start, end):
results = [] # maintain a list of results to avoid yielding
fringe = [(start, [])]
while fringe:
state, path = fringe.pop()
if path and state == end:
results.add(path) # don't yield any more, just add the path to the results list
else: # add an else block instead of using continue
for next_state in graph[state]:
if next_state not in path: # reverse the condition instead of continue
fringe.append((next_state, path+[next_state]))
return results # return the results at the end of the function
我注意到在大多数情况下,函数的生成器版本可能更好。使用continue
代替更多缩进更多的是样式选择,并且对代码的逻辑或性能没有太大影响(仅仅是它的外观)。