循环结构最好的办法
问题描述:
考虑同样的循环结构,这两个变种:循环结构最好的办法
x = find_number_of_iterations()
for n in range(x):
# do something in loop
和:
for n in range(find_number_of_iterations()):
# do something
将在第二循环评估每个后续循环运行的方法find_number_of_iterations
,还是会方法find_number_of_iterations
即使在第二个变体中也只能评估一次?
答
我怀疑你的导师的混乱可追溯到一个事实,即Python的for循环的语义是如此比在其他语言非常不同。
在像C语言的for循环是或多或少语法糖while循环:
for(i = 0; i < n; i++)
{
//do stuff
}
相当于:
i = 0;
while(i < n)
{
//do stuff
i++
}
在Python它是不同的。它的for循环是基于迭代器的。迭代器对象只进行一次初始化,然后在后续迭代中使用。下面的代码展示了Python的for循环是不(容易)翻译成一个while循环,并且也表明while循环您的导师的关注是有效的:
>>> def find_number_of_iterations():
print("called")
return 3
>>> for i in range(find_number_of_iterations()): print(i)
called
0
1
2
>>> i = 0
>>> while i < find_number_of_iterations():
print(i)
i += 1
called
0
called
1
called
2
called
答
无论哪种方式,该功能只被调用一次。您可以证明这一点,如下所示:
>>> def test_func():
"""Function to count calls and return integers."""
test_func.called += 1
return 3
# first version
>>> test_func.called = 0
>>> x = test_func()
>>> for _ in range(x):
print 'loop'
loop
loop
loop
>>> test_func.called
1
# second version
>>> test_func.called = 0
>>>
>>> for _ in range(test_func()):
print 'loop'
loop
loop
loop
>>> test_func.called
1
该函数被调用一次,调用该函数传递给range
(当时叫range
的结果遍历)的结果;这两个版本在逻辑上是等效的。
答
函数被调用一次。从逻辑上讲,是否每次迭代都要调用它,然后循环范围可能发生变化,从而导致各种严重破坏。这很容易测试:
def find_iterations():
print "find_iterations called"
return 5
for n in range(find_iterations()):
print n
结果:
$ python test.py
find_iterations called
0
1
2
3
4
你可以很容易地这个测试自己,而是:无论是方式,该功能只被调用一次。 – jonrsharpe
我该如何测试这个。我的导师批评我的代码在第二个变体中,因为他说它会在每个循环运行中评估 – oat
然后,你会告诉你的导师他们错了!你可以通过传递一个函数来测试它,该函数记录被调用的次数为find_number_of_iterations,然后检查是否为1。 – jonrsharpe