如何在Python中使用返回元组的函数的返回值作为while条件
我在找类似的东西,但没找到,所以就写出来了。
一些背景
我使用opencv从视频文件中提取帧。通常人们会用一个无尽的循环来做这件事,比如:
while (True):
s, img = cv.read()
或者
for i in xrange(10000): #just a big number
s, img = cv.read()
现在我想提取所有的帧,并在没有更多帧的时候退出循环。不过,我的python技能还不够强,无法做到我想做的事情。
我想知道的
read
函数(或者说方法,我不知道在python里怎么称呼)返回一个元组:第一个元素表示操作是否成功,第二个元素表示返回的帧。我想在元组的第一个元素为假时退出循环。因为我有C语言的背景,我想也许这样可以实现:
while ((success, img = capture.read())[0]):
#do sth with img
我以为这样在成功为假时会退出循环,但并没有成功。然后我想,也许这样可以:
while ((success, img = capture.read()).success):
#do sth with img
结果也没有成功。我不想做类似这样的事情:
while(True):
s, i = capture.read()
if (s == False):
break
我该如何在while
中测试这个条件,而不是在一个if
中,这样只有在成功时才会退出?
6 个回答
7
Python有一种替代的iter
用法,它的第一个参数是一个函数,第二个参数是一个哨兵值,用来决定什么时候停止。
使用这种方式,你可以写出类似这样的代码:
for s,img in iter(cv.read, (False, None)):
print img
不过,我还是怀疑这种方法是否比在if
块里直接用break
要好。
而且,它只能接受哨兵值作为返回的整体值,不能根据其中的一部分来决定停止条件(比如,不能根据元组的第一个值来判断)。虽然可以找到解决办法,但这样会让代码变得更加复杂:
>>> for s,img in itertools.takewhile(lambda x: x[0], iter(cv.read, None)):
print img
它使用itertools.takewhile
来判断返回的元组的第一个值是否等于False
,从而决定何时停止。
完整的测试版本:
>>> class Capture(object):
def __init__(self):
self.L = iter([1,2,3,4,5])
def read(self):
try:
img = self.L.next()
except StopIteration:
return (False,None)
return True, img
>>> cv = Capture()
>>> for s,img in iter(cv.read, (False, None)):
print img
1
2
3
4
5
>>> cv = Capture()
>>> for s,img in itertools.takewhile(lambda x: x[0], iter(cv.read, None)):
print img
1
2
3
4
5
20
你可以写一个生成器函数。
def readframes(cv):
while True:
success, frame = cv.read()
if success:
yield frame
else:
return
这样你就可以用一个for循环来遍历这些帧。
for frame in readframes(cv):
do_something_with_frame(frame)
7
想要更好地理解Python的编程风格,最好的办法就是暂时忘掉其他编程语言。
s = True
while s:
s, i = capture.read()
if s:
do_some_stuff(i)