I have a list consisting of like 20000 lists. I use each list’s 3rd element as a flag. I want to do some operations on this list as long as at least one element’s flag is 0, it’s like:
Since I couldn’t remove elements as I iterated over it, I invented these flags. But the my_list contains many items, and while loop reads all of them at each for loop, and it consumes lots of time! Do you have any suggestions?
The best answer here is to use all(), which is the builtin for this situation. We combine this with a generator expression to produce the result you want cleanly and efficiently. For example:
Note that all(flag == 0 for (_, _, flag) in items) is directly equivalent to all(item[2] == 0 for item in items), it’s just a little nicer to read in this case.
And, for the filter example, a list comprehension (of course, you could use a generator expression where appropriate):
>>> [x for x in items if x[2] == 0]
[[1, 2, 0], [1, 2, 0]]
If you want to check at least one element is 0, the better option is to use any() which is more readable:
>>> any(flag == 0 for (_, _, flag) in items)
True
回答 1
如果要检查列表中的任何项目是否违反条件,请使用all:
if all([x[2]==0for x in lista]):# Will run if all elements in the list has x[2] = 0 (use not to invert if necessary)
要删除所有不匹配的元素,请使用 filter
# Will remove all elements where x[2] is 0
listb = filter(lambda x: x[2]!=0, listb)
Another way to use itertools.ifilter. This checks truthiness and process
(using lambda)
Sample-
for x in itertools.ifilter(lambda x: x[2] == 0, my_list):
print x
回答 4
这种方式比使用以下方式更加灵活all():
my_list =[[1,2,0],[1,2,0],[1,2,0]]
all_zeros =FalseifFalsein[x[2]==0for x in my_list]elseTrue
any_zeros =TrueifTruein[x[2]==0for x in my_list]elseFalse
或更简洁地:
all_zeros =notFalsein[x[2]==0for x in my_list]
any_zeros =0in[x[2]for x in my_list]
my_list = [[1, 2, 0], [1, 2, 0], [1, 2, 0]]
all_zeros = False if False in [x[2] == 0 for x in my_list] else True
any_zeros = True if True in [x[2] == 0 for x in my_list] else False
or more succinctly:
all_zeros = not False in [x[2] == 0 for x in my_list]
any_zeros = 0 in [x[2] for x in my_list]
Many Python programmers are probably unaware that the syntax of while loops and for loops includes an optional else: clause:
for val in iterable:
do_something(val)
else:
clean_up()
The body of the else clause is a good place for certain kinds of clean-up actions, and is executed on normal termination of the loop: I.e., exiting the loop with return or break skips the else clause; exiting after a continue executes it. I know this only because I just looked it up (yet again), because I can never remember when the else clause is executed.
Always? On “failure” of the loop, as the name suggests? On regular termination? Even if the loop is exited with return? I can never be entirely sure without looking it up.
I blame my persisting uncertainty on the choice of keyword: I find else incredibly unmnemonic for this semantics. My question is not “why is this keyword used for this purpose” (which I would probably vote to close, though only after reading the answers and comments), but how can I think about the else keyword so that its semantics make sense, and I can therefore remember it?
I’m sure there was a fair amount of discussion about this, and I can imagine that the choice was made for consistency with the try statement’s else: clause (which I also have to look up), and with the goal of not adding to the list of Python’s reserved words. Perhaps the reasons for choosing else will clarify its function and make it more memorable, but I’m after connecting name to function, not after historical explanation per se.
The answers to this question, which my question was briefly closed as a duplicate of, contain a lot of interesting back story. My question has a different focus (how to connect the specific semantics of else with the keyword choice), but I feel there should be a link to this question somewhere.
An if statement runs its else clause if its condition evaluates to false.
Identically, a while loop runs the else clause if its condition evaluates to false.
This rule matches the behavior you described:
In normal execution, the while loop repeatedly runs until the condition evaluates to false, and therefore naturally exiting the loop runs the else clause.
When you execute a break statement, you exit out of the loop without evaluating the condition, so the condition cannot evaluate to false and you never run the else clause.
When you execute a continue statement, you evaluate the condition again, and do exactly what you normally would at the beginning of a loop iteration.
So, if the condition is true, you keep looping, but if it is false you run the else clause.
Other methods of exiting the loop, such as return, do not evaluate the condition and therefore do not run the else clause.
for loops behave the same way. Just consider the condition as true if the iterator has more elements, or false otherwise.
Better to think of it this way: The else block will always be executed if everything goes right in the preceding for block such that it reaches exhaustion.
Right in this context will mean no exception, no break, no return. Any statement that hijacks control from for will cause the else block to be bypassed.
A common use case is found when searching for an item in an iterable, for which the search is either called off when the item is found or a "not found" flag is raised/printed via the following else block:
for items in basket:
if isinstance(item, Egg):
break
else:
print("No eggs in basket")
A continue does not hijack control from for, so control will proceed to the else after the for is exhausted.
When does an if execute an else? When its condition is false. It is exactly the same for the while/else. So you can think of while/else as just an if that keeps running its true condition until it evaluates false. A break doesn’t change that. It just jumps out of the containing loop with no evaluation. The else is only executed if evaluating the if/while condition is false.
The for is similar, except its false condition is exhausting its iterator.
continue and break don’t execute else. That isn’t their function. The break exits the containing loop. The continue goes back to the top of the containing loop, where the loop condition is evaluated. It is the act of evaluating if/while to false (or for has no more items) that executes else and no other way.
回答 3
这实际上是什么意思:
for/while...:if...:breakif there was a break:passelse:...
这是编写这种常见模式的一种更好的方式:
found =Falsefor/while...:if...:
found =Truebreakifnot found:...
for/while ...:
if ...:
break
if there was a break:
pass
else:
...
It’s a nicer way of writing of this common pattern:
found = False
for/while ...:
if ...:
found = True
break
if not found:
...
The else clause will not be executed if there is a return because return leaves the function, as it is meant to. The only exception to that which you may be thinking of is finally, whose purpose is to be sure that it is always executed.
continue has nothing special to do with this matter. It causes the current iteration of the loop to end which may happen to end the entire loop, and clearly in that case the loop wasn’t ended by a break.
try/else is similar:
try:
...
except:
...
if there was an exception:
pass
else:
...
回答 4
如果您将循环视为与此类似的结构(某种伪代码):
loop:if condition then
...//execute body
goto loop
else...
If you think of your loops as a structure similar to this (somewhat pseudo-code):
loop:
if condition then
... //execute body
goto loop
else
...
it might make a little bit more sense. A loop is essentially just an if statement that is repeated until the condition is false. And this is the important point. The loop checks its condition and sees that it’s false, thus executes the else (just like a normal if/else) and then the loop is done.
So notice that the elseonly get’s executed when the condition is checked. That means that if you exit the body of the loop in the middle of execution with for example a return or a break, since the condition is not checked again, the else case won’t be executed.
A continue on the other hand stops the current execution and then jumps back to check the condition of the loop again, which is why the else can be reached in this scenario.
My gotcha moment with the loop’s else clause was when I was watching a talk by Raymond Hettinger, who told a story about how he thought it should have been called nobreak. Take a look at the following code, what do you think it would do?
for i in range(10):
if test(i):
break
# ... work with i
nobreak:
print('Loop completed')
What would you guess it does? Well, the part that says nobreak would only be executed if a break statement wasn’t hit in the loop.
回答 6
通常,我倾向于想到这样的循环结构:
for item in my_sequence:if logic(item):
do_something(item)break
非常像可变数量的if/elif语句:
if logic(my_seq[0]):
do_something(my_seq[0])elif logic(my_seq[1]):
do_something(my_seq[1])elif logic(my_seq[2]):
do_something(my_seq[2])....elif logic(my_seq[-1]):
do_something(my_seq[-1])
In this case the else statement on the for loop works exactly like the else statement on the chain of elifs, it only executes if none of the conditions before it evaluate to True. (or break execution with return or an exception) If my loop does not fit this specification usually I choose to opt out of using for: else for the exact reason you posted this question: it is non-intuitive.
Others have already explained the mechanics of while/for...else, and the Python 3 language reference has the authoritative definition (see while and for), but here is my personal mnemonic, FWIW. I guess the key for me has been to break this down into two parts: one for understanding the meaning of the else in relation to the loop conditional, and one for understanding loop control.
I find it’s easiest to start by understanding while...else:
while you have more items, do stuff, else if you run out, do this
The for...else mnemonic is basically the same:
for every item, do stuff, but else if you run out, do this
In both cases, the else part is only reached once there are no more items to process, and the last item has been processed in a regular manner (i.e. no break or return). A continue just goes back and sees if there are any more items. My mnemonic for these rules applies to both while and for:
when breaking or returning, there’s nothing else to do,
and when I say continue, that’s “loop back to start” for you
– with “loop back to start” meaning, obviously, the start of the loop where we check whether there are any more items in the iterable, so as far as the else is concerned, continue really plays no role at all.
In the linked article at 8thlight blog, the Word Wrap kata is considered: adding line breaks to strings (the s variable in the snippets below) to make them fit a given width (the length variable in the snippets below). At one point the implementation looks as follows (Java):
String result = "";
if (s.length() > length) {
result = s.substring(0, length) + "\n" + s.substring(length);
} else {
result = s;
}
return result;
So we have code that works conditionally: when a particular condition is met, a line break is added. We want to improve the code to handle multiple line breaks. The solution presented in the article proposes to apply the (if->while) transformation, however the author makes a comment that:
While loops can’t have else clauses, so we need to eliminate the else path by doing less in the if path. Again, this is a refactoring.
which forces to do more changes to the code in the context of one failing test:
String result = "";
while (s.length() > length) {
result += s.substring(0, length) + "\n";
s = s.substring(length);
}
result += s;
In TDD we want to write as less code as possible to make tests pass. Thanks to Python’s syntax the following transformation is possible:
from:
result = ""
if len(s) > length:
result = s[0:length] + "\n"
s = s[length:]
else:
result += s
to:
result = ""
while len(s) > length:
result += s[0:length] + "\n"
s = s[length:]
else:
result += s
The way I see it, else: fires when you iterate past the end of the loop.
If you break or return or raise you don’t iterate past the end of loop, you stop immeadiately, and thus the else: block won’t run. If you continue you still iterate past the end of loop, since continue just skips to the next iteration. It doesn’t stop the loop.
Think of the else clause as being part of the loop construct; break breaks out of the loop construct entirely, and thus skips the else clause.
But really, my mental mapping is simply that it’s the ‘structured’ version of the pattern C/C++ pattern:
for (...) {
...
if (test) { goto done; }
...
}
...
done:
...
So when I encounter for...else or write it myself, rather than understand it directly, I mentally translate it into the above understanding of the pattern and then work out which parts of the python syntax map to which parts of the pattern.
(I put ‘structured’ in scare quotes because the difference is not whether the code is structured or unstructured, but merely whether there are keywords and grammar dedicated to the particular structure)
If you pair else with for, it could be confusing. I don’t think the keyword else was a great choice for this syntax, but if you pair else with if which contains break, you can see it actually makes sense. else is barely useful if there is no preceding if statement and I believe this is why the syntax designer chose the keyword.
Let me demonstrate it in human language.
for each person in a group of suspects if anyone is the criminal
break the investigation. else report failure.
The way I think about it, the key is to consider the meaning of continue rather than else.
The other keywords you mention break out of the loop (exit abnormally) whilst continue does not, it just skips the remainder of the code block inside the loop. The fact that it can precede loop termination is incidental: the termination is actually done in the normal way by evaluation of the loop conditional expression.
Then you just need to remember that the else clause is executed after normal loop termination.
回答 13
# tested in Python 3.6.4def buy_fruit(fruits):'''I translate the 'else' below into 'if no break' from for loop '''for fruit in fruits:if'rotten'in fruit:print(f'do not want to buy {fruit}')breakelse:#if no breakprint(f'ready to buy {fruits}')if __name__ =='__main__':
a_bag_of_apples =['golden delicious','honeycrisp','rotten mcintosh']
b_bag_of_apples =['granny smith','red delicious','honeycrisp','gala','fuji']
buy_fruit(a_bag_of_apples)
buy_fruit(b_bag_of_apples)'''
do not want to buy rotten mcintosh
ready to buy ['granny smith', 'red delicious', 'honeycrisp', 'gala', 'fuji']
'''
# tested in Python 3.6.4
def buy_fruit(fruits):
'''I translate the 'else' below into 'if no break' from for loop '''
for fruit in fruits:
if 'rotten' in fruit:
print(f'do not want to buy {fruit}')
break
else: #if no break
print(f'ready to buy {fruits}')
if __name__ == '__main__':
a_bag_of_apples = ['golden delicious', 'honeycrisp', 'rotten mcintosh']
b_bag_of_apples = ['granny smith', 'red delicious', 'honeycrisp', 'gala', 'fuji']
buy_fruit(a_bag_of_apples)
buy_fruit(b_bag_of_apples)
'''
do not want to buy rotten mcintosh
ready to buy ['granny smith', 'red delicious', 'honeycrisp', 'gala', 'fuji']
'''
fig = plt.figure()
plt.axis([0,1000,0,1])
i =0
x = list()
y = list()while i <1000:
temp_y = np.random.random()
x.append(i)
y.append(temp_y)
plt.scatter(i, temp_y)
i +=1
plt.show()
I am trying to plot some data from a camera in real time using OpenCV. However, the real-time plotting (using matplotlib) doesn’t seem to be working.
I’ve isolated the problem into this simple example:
fig = plt.figure()
plt.axis([0, 1000, 0, 1])
i = 0
x = list()
y = list()
while i < 1000:
temp_y = np.random.random()
x.append(i)
y.append(temp_y)
plt.scatter(i, temp_y)
i += 1
plt.show()
I would expect this example to plot 1000 points individually. What actually happens is that the window pops up with the first point showing (ok with that), then waits for the loop to finish before it populates the rest of the graph.
Any thoughts why I am not seeing points populated one at a time?
import numpy as npimport matplotlib.pyplot as plt
plt.axis([0,10,0,1])for i in range(10):
y = np.random.random()
plt.scatter(i, y)
plt.pause(0.05)
plt.show()
Here’s the working version of the code in question (requires at least version Matplotlib 1.1.0 from 2011-11-14):
import numpy as np
import matplotlib.pyplot as plt
plt.axis([0, 10, 0, 1])
for i in range(10):
y = np.random.random()
plt.scatter(i, y)
plt.pause(0.05)
plt.show()
Note some of the changes:
Call plt.pause(0.05) to both draw the new data and it runs the GUI’s event loop (allowing for mouse interaction).
If you’re interested in realtime plotting, I’d recommend looking into matplotlib’s animation API. In particular, using blit to avoid redrawing the background on every frame can give you substantial speed gains (~10x):
#!/usr/bin/env python
import numpy as np
import time
import matplotlib
matplotlib.use('GTKAgg')
from matplotlib import pyplot as plt
def randomwalk(dims=(256, 256), n=20, sigma=5, alpha=0.95, seed=1):
""" A simple random walk with memory """
r, c = dims
gen = np.random.RandomState(seed)
pos = gen.rand(2, n) * ((r,), (c,))
old_delta = gen.randn(2, n) * sigma
while True:
delta = (1. - alpha) * gen.randn(2, n) * sigma + alpha * old_delta
pos += delta
for ii in xrange(n):
if not (0. <= pos[0, ii] < r):
pos[0, ii] = abs(pos[0, ii] % r)
if not (0. <= pos[1, ii] < c):
pos[1, ii] = abs(pos[1, ii] % c)
old_delta = delta
yield pos
def run(niter=1000, doblit=True):
"""
Display the simulation using matplotlib, optionally using blit for speed
"""
fig, ax = plt.subplots(1, 1)
ax.set_aspect('equal')
ax.set_xlim(0, 255)
ax.set_ylim(0, 255)
ax.hold(True)
rw = randomwalk()
x, y = rw.next()
plt.show(False)
plt.draw()
if doblit:
# cache the background
background = fig.canvas.copy_from_bbox(ax.bbox)
points = ax.plot(x, y, 'o')[0]
tic = time.time()
for ii in xrange(niter):
# update the xy data
x, y = rw.next()
points.set_data(x, y)
if doblit:
# restore background
fig.canvas.restore_region(background)
# redraw just the points
ax.draw_artist(points)
# fill in the axes rectangle
fig.canvas.blit(ax.bbox)
else:
# redraw everything
fig.canvas.draw()
plt.close(fig)
print "Blit = %s, average FPS: %.2f" % (
str(doblit), niter / (time.time() - tic))
if __name__ == '__main__':
run(doblit=False)
run(doblit=True)
Output:
Blit = False, average FPS: 54.37
Blit = True, average FPS: 438.27
回答 2
我知道我回答这个问题有点晚了。不过,我前段时间已经编写了一些代码来绘制实时图形,我想分享一下:
PyQt4的代码:
#################################################################### ## PLOT A LIVE GRAPH (PyQt4) ## ----------------------------- ## EMBED A MATPLOTLIB ANIMATION INSIDE YOUR ## OWN GUI! ## ####################################################################import sysimport osfromPyQt4importQtGuifromPyQt4importQtCoreimport functoolsimport numpy as npimport random as rdimport matplotlib
matplotlib.use("Qt4Agg")from matplotlib.figure importFigurefrom matplotlib.animation importTimedAnimationfrom matplotlib.lines importLine2Dfrom matplotlib.backends.backend_qt4agg importFigureCanvasQTAggasFigureCanvasimport timeimport threadingdef setCustomSize(x, width, height):
sizePolicy =QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed,QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(x.sizePolicy().hasHeightForWidth())
x.setSizePolicy(sizePolicy)
x.setMinimumSize(QtCore.QSize(width, height))
x.setMaximumSize(QtCore.QSize(width, height))''''''classCustomMainWindow(QtGui.QMainWindow):def __init__(self):
super(CustomMainWindow, self).__init__()# Define the geometry of the main window
self.setGeometry(300,300,800,400)
self.setWindowTitle("my first window")# Create FRAME_A
self.FRAME_A =QtGui.QFrame(self)
self.FRAME_A.setStyleSheet("QWidget { background-color: %s }"%QtGui.QColor(210,210,235,255).name())
self.LAYOUT_A =QtGui.QGridLayout()
self.FRAME_A.setLayout(self.LAYOUT_A)
self.setCentralWidget(self.FRAME_A)# Place the zoom button
self.zoomBtn =QtGui.QPushButton(text ='zoom')
setCustomSize(self.zoomBtn,100,50)
self.zoomBtn.clicked.connect(self.zoomBtnAction)
self.LAYOUT_A.addWidget(self.zoomBtn,*(0,0))# Place the matplotlib figure
self.myFig =CustomFigCanvas()
self.LAYOUT_A.addWidget(self.myFig,*(0,1))# Add the callbackfunc to ..
myDataLoop = threading.Thread(name ='myDataLoop', target = dataSendLoop, daemon =True, args =(self.addData_callbackFunc,))
myDataLoop.start()
self.show()''''''def zoomBtnAction(self):print("zoom in")
self.myFig.zoomIn(5)''''''def addData_callbackFunc(self, value):# print("Add data: " + str(value))
self.myFig.addData(value)''' End Class '''classCustomFigCanvas(FigureCanvas,TimedAnimation):def __init__(self):
self.addedData =[]print(matplotlib.__version__)# The data
self.xlim =200
self.n = np.linspace(0, self.xlim -1, self.xlim)
a =[]
b =[]
a.append(2.0)
a.append(4.0)
a.append(2.0)
b.append(4.0)
b.append(3.0)
b.append(4.0)
self.y =(self.n *0.0)+50# The window
self.fig =Figure(figsize=(5,5), dpi=100)
self.ax1 = self.fig.add_subplot(111)# self.ax1 settings
self.ax1.set_xlabel('time')
self.ax1.set_ylabel('raw data')
self.line1 =Line2D([],[], color='blue')
self.line1_tail =Line2D([],[], color='red', linewidth=2)
self.line1_head =Line2D([],[], color='red', marker='o', markeredgecolor='r')
self.ax1.add_line(self.line1)
self.ax1.add_line(self.line1_tail)
self.ax1.add_line(self.line1_head)
self.ax1.set_xlim(0, self.xlim -1)
self.ax1.set_ylim(0,100)FigureCanvas.__init__(self, self.fig)TimedAnimation.__init__(self, self.fig, interval =50, blit =True)def new_frame_seq(self):return iter(range(self.n.size))def _init_draw(self):
lines =[self.line1, self.line1_tail, self.line1_head]for l in lines:
l.set_data([],[])def addData(self, value):
self.addedData.append(value)def zoomIn(self, value):
bottom = self.ax1.get_ylim()[0]
top = self.ax1.get_ylim()[1]
bottom += value
top -= value
self.ax1.set_ylim(bottom,top)
self.draw()def _step(self,*args):# Extends the _step() method for the TimedAnimation class.try:TimedAnimation._step(self,*args)exceptExceptionas e:
self.abc +=1print(str(self.abc))TimedAnimation._stop(self)passdef _draw_frame(self, framedata):
margin =2while(len(self.addedData)>0):
self.y = np.roll(self.y,-1)
self.y[-1]= self.addedData[0]del(self.addedData[0])
self.line1.set_data(self.n[0: self.n.size - margin ], self.y[0: self.n.size - margin ])
self.line1_tail.set_data(np.append(self.n[-10:-1- margin], self.n[-1- margin]), np.append(self.y[-10:-1- margin], self.y[-1- margin]))
self.line1_head.set_data(self.n[-1- margin], self.y[-1- margin])
self._drawn_artists =[self.line1, self.line1_tail, self.line1_head]''' End Class '''# You need to setup a signal slot mechanism, to # send data to your GUI in a thread-safe way.# Believe me, if you don't do this right, things# go very very wrong..classCommunicate(QtCore.QObject):
data_signal =QtCore.pyqtSignal(float)''' End Class '''def dataSendLoop(addData_callbackFunc):# Setup the signal-slot mechanism.
mySrc =Communicate()
mySrc.data_signal.connect(addData_callbackFunc)# Simulate some data
n = np.linspace(0,499,500)
y =50+25*(np.sin(n /8.3))+10*(np.sin(n /7.5))-5*(np.sin(n /1.5))
i =0while(True):if(i >499):
i =0
time.sleep(0.1)
mySrc.data_signal.emit(y[i])# <- Here you emit a signal!
i +=1######if __name__=='__main__':
app =QtGui.QApplication(sys.argv)QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('Plastique'))
myGUI =CustomMainWindow()
sys.exit(app.exec_())''''''
我最近重写了PyQt5的代码。 PyQt5的代码:
#################################################################### ## PLOT A LIVE GRAPH (PyQt5) ## ----------------------------- ## EMBED A MATPLOTLIB ANIMATION INSIDE YOUR ## OWN GUI! ## ####################################################################import sysimport osfromPyQt5.QtWidgetsimport*fromPyQt5.QtCoreimport*fromPyQt5.QtGuiimport*import functoolsimport numpy as npimport random as rdimport matplotlib
matplotlib.use("Qt5Agg")from matplotlib.figure importFigurefrom matplotlib.animation importTimedAnimationfrom matplotlib.lines importLine2Dfrom matplotlib.backends.backend_qt5agg importFigureCanvasQTAggasFigureCanvasimport timeimport threadingclassCustomMainWindow(QMainWindow):def __init__(self):
super(CustomMainWindow, self).__init__()# Define the geometry of the main window
self.setGeometry(300,300,800,400)
self.setWindowTitle("my first window")# Create FRAME_A
self.FRAME_A =QFrame(self)
self.FRAME_A.setStyleSheet("QWidget { background-color: %s }"%QColor(210,210,235,255).name())
self.LAYOUT_A =QGridLayout()
self.FRAME_A.setLayout(self.LAYOUT_A)
self.setCentralWidget(self.FRAME_A)# Place the zoom button
self.zoomBtn =QPushButton(text ='zoom')
self.zoomBtn.setFixedSize(100,50)
self.zoomBtn.clicked.connect(self.zoomBtnAction)
self.LAYOUT_A.addWidget(self.zoomBtn,*(0,0))# Place the matplotlib figure
self.myFig =CustomFigCanvas()
self.LAYOUT_A.addWidget(self.myFig,*(0,1))# Add the callbackfunc to ..
myDataLoop = threading.Thread(name ='myDataLoop', target = dataSendLoop, daemon =True, args =(self.addData_callbackFunc,))
myDataLoop.start()
self.show()returndef zoomBtnAction(self):print("zoom in")
self.myFig.zoomIn(5)returndef addData_callbackFunc(self, value):# print("Add data: " + str(value))
self.myFig.addData(value)return''' End Class '''classCustomFigCanvas(FigureCanvas,TimedAnimation):def __init__(self):
self.addedData =[]print(matplotlib.__version__)# The data
self.xlim =200
self.n = np.linspace(0, self.xlim -1, self.xlim)
a =[]
b =[]
a.append(2.0)
a.append(4.0)
a.append(2.0)
b.append(4.0)
b.append(3.0)
b.append(4.0)
self.y =(self.n *0.0)+50# The window
self.fig =Figure(figsize=(5,5), dpi=100)
self.ax1 = self.fig.add_subplot(111)# self.ax1 settings
self.ax1.set_xlabel('time')
self.ax1.set_ylabel('raw data')
self.line1 =Line2D([],[], color='blue')
self.line1_tail =Line2D([],[], color='red', linewidth=2)
self.line1_head =Line2D([],[], color='red', marker='o', markeredgecolor='r')
self.ax1.add_line(self.line1)
self.ax1.add_line(self.line1_tail)
self.ax1.add_line(self.line1_head)
self.ax1.set_xlim(0, self.xlim -1)
self.ax1.set_ylim(0,100)FigureCanvas.__init__(self, self.fig)TimedAnimation.__init__(self, self.fig, interval =50, blit =True)returndef new_frame_seq(self):return iter(range(self.n.size))def _init_draw(self):
lines =[self.line1, self.line1_tail, self.line1_head]for l in lines:
l.set_data([],[])returndef addData(self, value):
self.addedData.append(value)returndef zoomIn(self, value):
bottom = self.ax1.get_ylim()[0]
top = self.ax1.get_ylim()[1]
bottom += value
top -= value
self.ax1.set_ylim(bottom,top)
self.draw()returndef _step(self,*args):# Extends the _step() method for the TimedAnimation class.try:TimedAnimation._step(self,*args)exceptExceptionas e:
self.abc +=1print(str(self.abc))TimedAnimation._stop(self)passreturndef _draw_frame(self, framedata):
margin =2while(len(self.addedData)>0):
self.y = np.roll(self.y,-1)
self.y[-1]= self.addedData[0]del(self.addedData[0])
self.line1.set_data(self.n[0: self.n.size - margin ], self.y[0: self.n.size - margin ])
self.line1_tail.set_data(np.append(self.n[-10:-1- margin], self.n[-1- margin]), np.append(self.y[-10:-1- margin], self.y[-1- margin]))
self.line1_head.set_data(self.n[-1- margin], self.y[-1- margin])
self._drawn_artists =[self.line1, self.line1_tail, self.line1_head]return''' End Class '''# You need to setup a signal slot mechanism, to# send data to your GUI in a thread-safe way.# Believe me, if you don't do this right, things# go very very wrong..classCommunicate(QObject):
data_signal = pyqtSignal(float)''' End Class '''def dataSendLoop(addData_callbackFunc):# Setup the signal-slot mechanism.
mySrc =Communicate()
mySrc.data_signal.connect(addData_callbackFunc)# Simulate some data
n = np.linspace(0,499,500)
y =50+25*(np.sin(n /8.3))+10*(np.sin(n /7.5))-5*(np.sin(n /1.5))
i =0while(True):if(i >499):
i =0
time.sleep(0.1)
mySrc.data_signal.emit(y[i])# <- Here you emit a signal!
i +=1######if __name__=='__main__':
app =QApplication(sys.argv)QApplication.setStyle(QStyleFactory.create('Plastique'))
myGUI =CustomMainWindow()
sys.exit(app.exec_())
show is probably not the best choice for this. What I would do is use pyplot.draw() instead. You also might want to include a small time delay (e.g., time.sleep(0.05)) in the loop so that you can see the plots happening. If I make these changes to your example it works for me and I see each point appearing one at a time.
The top (and many other) answers were built upon plt.pause(), but that was an old way of animating the plot in matplotlib. It is not only slow, but also causes focus to be grabbed upon each update (I had a hard time stopping the plotting python process).
After digging around various answers and pieces of code, this in fact proved to be a smooth way of drawing incoming data infinitely for me.
Here is my code for a quick start. It plots current time with a random number in [0, 100) every 200ms infinitely, while also handling auto rescaling of the view:
from datetime import datetime
from matplotlib import pyplot
from matplotlib.animation import FuncAnimation
from random import randrange
x_data, y_data = [], []
figure = pyplot.figure()
line, = pyplot.plot_date(x_data, y_data, '-')
def update(frame):
x_data.append(datetime.now())
y_data.append(randrange(0, 100))
line.set_data(x_data, y_data)
figure.gca().relim()
figure.gca().autoscale_view()
return line,
animation = FuncAnimation(figure, update, interval=200)
pyplot.show()
import matplotlib.pyplot as plt
from drawnow import drawnow
def make_fig():
plt.scatter(x, y)# I think you meant this
plt.ion()# enable interactivity
fig = plt.figure()# make a figure
x = list()
y = list()for i in range(1000):
temp_y = np.random.random()
x.append(i)
y.append(temp_y)# or any arbitrary update to your figure's data
i +=1
drawnow(make_fig)
I know this question is old, but there’s now a package available called drawnow on GitHub as “python-drawnow”. This provides an interface similar to MATLAB’s drawnow — you can easily update a figure.
An example for your use case:
import matplotlib.pyplot as plt
from drawnow import drawnow
def make_fig():
plt.scatter(x, y) # I think you meant this
plt.ion() # enable interactivity
fig = plt.figure() # make a figure
x = list()
y = list()
for i in range(1000):
temp_y = np.random.random()
x.append(i)
y.append(temp_y) # or any arbitrary update to your figure's data
i += 1
drawnow(make_fig)
python-drawnow is a thin wrapper around plt.draw but provides the ability to confirm (or debug) after figure display.
The problem seems to be that you expect plt.show() to show the window and then to return. It does not do that. The program will stop at that point and only resume once you close the window. You should be able to test that: If you close the window and then another window should pop up.
To resolve that problem just call plt.show() once after your loop. Then you get the complete plot. (But not a ‘real-time plotting’)
You can try setting the keyword-argument block like this: plt.show(block=False) once at the beginning and then use .draw() to update.
回答 8
这是我必须在系统上使用的版本。
import matplotlib.pyplot as plt
from drawnow import drawnow
import numpy as np
def makeFig():
plt.scatter(xList,yList)# I think you meant this
plt.ion()# enable interactivity
fig=plt.figure()# make a figure
xList=list()
yList=list()for i in np.arange(50):
y=np.random.random()
xList.append(i)
yList.append(y)
drawnow(makeFig)#makeFig() The drawnow(makeFig) command can be replaced#plt.draw() with makeFig(); plt.draw()
plt.pause(0.001)
Here is a version that I got to work on my system.
import matplotlib.pyplot as plt
from drawnow import drawnow
import numpy as np
def makeFig():
plt.scatter(xList,yList) # I think you meant this
plt.ion() # enable interactivity
fig=plt.figure() # make a figure
xList=list()
yList=list()
for i in np.arange(50):
y=np.random.random()
xList.append(i)
yList.append(y)
drawnow(makeFig)
#makeFig() The drawnow(makeFig) command can be replaced
#plt.draw() with makeFig(); plt.draw()
plt.pause(0.001)
The drawnow(makeFig) line can be replaced with a makeFig(); plt.draw() sequence and it still works OK.
回答 9
如果要绘制而不在绘制更多点时冻结线程,则应使用plt.pause()而不是time.sleep()
im使用以下代码绘制一系列xy坐标。
import matplotlib.pyplot as plt
import math
pi =3.14159
fig, ax = plt.subplots()
x =[]
y =[]defPointsInCircum(r,n=20):
circle =[(math.cos(2*pi/n*x)*r,math.sin(2*pi/n*x)*r)for x in xrange(0,n+1)]return circle
circle_list =PointsInCircum(3,50)for t in range(len(circle_list)):if t ==0:
points,= ax.plot(x, y, marker='o', linestyle='--')
ax.set_xlim(-4,4)
ax.set_ylim(-4,4)else:
x_coord, y_coord = circle_list.pop()
x.append(x_coord)
y.append(y_coord)
points.set_data(x, y)
plt.pause(0.01)
If you want draw and not freeze your thread as more point are drawn you should use plt.pause() not time.sleep()
im using the following code to plot a series of xy coordinates.
import matplotlib.pyplot as plt
import math
pi = 3.14159
fig, ax = plt.subplots()
x = []
y = []
def PointsInCircum(r,n=20):
circle = [(math.cos(2*pi/n*x)*r,math.sin(2*pi/n*x)*r) for x in xrange(0,n+1)]
return circle
circle_list = PointsInCircum(3, 50)
for t in range(len(circle_list)):
if t == 0:
points, = ax.plot(x, y, marker='o', linestyle='--')
ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)
else:
x_coord, y_coord = circle_list.pop()
x.append(x_coord)
y.append(y_coord)
points.set_data(x, y)
plt.pause(0.01)
from bokeh.plotting import curdoc, figure
import random
import time
def update():global i
temp_y = random.random()
r.data_source.stream({'x':[i],'y':[temp_y]})
i +=1
i =0
p = figure()
r = p.circle([],[])
curdoc().add_root(p)
curdoc().add_periodic_callback(update,100)
Another option is to go with bokeh. IMO, it is a good alternative at least for real-time plots. Here is a bokeh version of the code in the question:
from bokeh.plotting import curdoc, figure
import random
import time
def update():
global i
temp_y = random.random()
r.data_source.stream({'x': [i], 'y': [temp_y]})
i += 1
i = 0
p = figure()
r = p.circle([], [])
curdoc().add_root(p)
curdoc().add_periodic_callback(update, 100)
and for running it:
pip3 install bokeh
bokeh serve --show test.py
bokeh shows the result in a web browser via websocket communications. It is especially useful when data is generated by remote headless server processes.
回答 11
一个实时绘制CPU使用情况的示例用例。
import time
import psutil
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
i =0
x, y =[],[]whileTrue:
x.append(i)
y.append(psutil.cpu_percent())
ax.plot(x, y, color='b')
fig.canvas.draw()
ax.set_xlim(left=max(0, i -50), right=i +50)
fig.show()
plt.pause(0.05)
i +=1
while condition:
handle_true()else:# condition is false now, handle and go on with the rest of the program
handle_false()
一个示例可能类似于:
while value < threshold:ifnot process_acceptable_value(value):# something went wrong, exit the loop; don't pass go, don't collect 200break
value = update(value)else:# value >= threshold; pass go, collect 200
handle_threshold_reached()
The else clause is only executed when your while condition becomes false. If you break out of the loop, or if an exception is raised, it won’t be executed.
One way to think about it is as an if/else construct with respect to the condition:
if condition:
handle_true()
else:
handle_false()
is analogous to the looping construct:
while condition:
handle_true()
else:
# condition is false now, handle and go on with the rest of the program
handle_false()
An example might be along the lines of:
while value < threshold:
if not process_acceptable_value(value):
# something went wrong, exit the loop; don't pass go, don't collect 200
break
value = update(value)
else:
# value >= threshold; pass go, collect 200
handle_threshold_reached()
The else clause is executed if you exit a block normally, by hitting the loop condition or falling off the bottom of a try block. It is not executed if you break or return out of a block, or raise an exception. It works for not only while and for loops, but also try blocks.
You typically find it in places where normally you would exit a loop early, and running off the end of the loop is an unexpected/unusual occasion. For example, if you’re looping through a list looking for a value:
for value in values:
if value == 5:
print "Found it!"
break
else:
print "Nowhere to be found. :-("
回答 2
作为对的答复Is there a specific reason?,这是一个有趣的应用程序:突破了多个循环级别。
for k in[2,3,5,7,11,13,17,25]:for m in range(2,10):if k == m:continueprint'trying %s %% %s'%(k, m)if k % m ==0:print'found a divisor: %d %% %d; breaking out of loop'%(k, m)breakelse:continueprint'breaking another level of loop'breakelse:print'no divisor could be found!'
In reply to Is there a specific reason?, here is one interesting application: breaking out of multiple levels of looping.
Here is how it works: the outer loop has a break at the end, so it would only be executed once. However, if the inner loop completes (finds no divisor), then it reaches the else statement and the outer break is never reached. This way, a break in the inner loop will break out of both loops, rather than just one.
for k in [2, 3, 5, 7, 11, 13, 17, 25]:
for m in range(2, 10):
if k == m:
continue
print 'trying %s %% %s' % (k, m)
if k % m == 0:
print 'found a divisor: %d %% %d; breaking out of loop' % (k, m)
break
else:
continue
print 'breaking another level of loop'
break
else:
print 'no divisor could be found!'
For both while and for loops, the else statement is executed at the end, unless break was used.
In most cases there are better ways to do this (wrapping it into a function or raising an exception), but this works!
The while statement is used for repeated execution as long as an expression is true:
while_stmt ::= "while" expression ":" suite
["else" ":" suite]
This repeatedly tests the expression and, if it is true, executes the first suite; if the expression is false (which may be the first time it is tested) the suite of the else clause, if present, is executed and the loop terminates.
A break statement executed in the first suite terminates the loop without executing the else clause’s suite. A continue statement executed in the first suite skips the rest of the suite and goes back to testing the expression.
回答 4
我的回答将集中于何时可以使用while / for-else。
乍一看,使用时似乎没有什么不同
while CONDITION:
EXPRESSIONS
print'ELSE'print'The next statement'
和
while CONDITION:
EXPRESSIONS
else:print'ELSE'print'The next statement'
My answer will focus on WHEN we can use while/for-else.
At the first glance, it seems there is no different when using
while CONDITION:
EXPRESSIONS
print 'ELSE'
print 'The next statement'
and
while CONDITION:
EXPRESSIONS
else:
print 'ELSE'
print 'The next statement'
Because the print 'ELSE' statement seems always executed in both cases (both when the while loop finished or not run).
Then, it’s only different when the statement print 'ELSE' will not be executed.
It’s when there is a breakinside the code block under while
In [17]: i = 0
In [18]: while i < 5:
print i
if i == 2:
break
i = i +1
else:
print 'ELSE'
print 'The next statement'
....:
0
1
2
The next statement
If differ to:
In [19]: i = 0
In [20]: while i < 5:
print i
if i == 2:
break
i = i +1
print 'ELSE'
print 'The next statement'
....:
0
1
2
ELSE
The next statement
return is not in this category, because it does the same effect for two above cases.
exception raise also does not cause difference, because when it raises, where the next code will be executed is in exception handler (except block), the code in else clause or right after the while clause will not be executed.
runner_at =0# or 10 makes no difference, if unlucky_sector is not 0-10
unlucky_sector =6while runner_at <10:print("Runner at: ", runner_at)if runner_at == unlucky_sector:print("Runner fell and broke his foot. Will not reach finish.")break
runner_at +=1else:print("Runner has finished the race!")# Not executed if runner broke his foot.
for i in[1,2,3]:for j in['a','unlucky','c']:print(i, j)if j =='unlucky':breakelse:continue# Only executed if inner loop didn't break.break# This is only reached if inner loop 'breaked' out since continue didn't run. print("Finished")# 1 a# 1 b# Finished
I kinda like to think of it with a ‘runner’ metaphor.
The “else” is like crossing the finish line, irrelevant of whether you started at the beginning or end of the track. “else” is only not executed if you break somewhere in between.
runner_at = 0 # or 10 makes no difference, if unlucky_sector is not 0-10
unlucky_sector = 6
while runner_at < 10:
print("Runner at: ", runner_at)
if runner_at == unlucky_sector:
print("Runner fell and broke his foot. Will not reach finish.")
break
runner_at += 1
else:
print("Runner has finished the race!") # Not executed if runner broke his foot.
Main use cases is using this breaking out of nested loops or if you want to run some statements only if loop didn’t break somewhere (think of breaking being an unusual situation).
For example, the following is a mechanism on how to break out of an inner loop without using variables or try/catch:
for i in [1,2,3]:
for j in ['a', 'unlucky', 'c']:
print(i, j)
if j == 'unlucky':
break
else:
continue # Only executed if inner loop didn't break.
break # This is only reached if inner loop 'breaked' out since continue didn't run.
print("Finished")
# 1 a
# 1 b
# Finished
The better use of ‘while: else:’ construction in Python should be if no loop is executed in ‘while’ then the ‘else’ statement is executed. The way it works today doesn’t make sense because you can use the code below with the same results…
n = 5
while n != 0:
print n
n -= 1
print "what the..."
回答 10
这对于社交互动很有用。
while(Date!="January 1st"):
time.sleep(1)else:print("Happy new year!")
list_of_ints =[1,2,3]
iterator = list_of_ints.__iter__()
element =NonewhileTrue:if element:print elementtry:
element = iterator.next()exceptStopIteration:breakprint"done"
代替“ 1,2,3,done”,它输出以下输出:
[stdout:]1[stdout:]2[stdout:]3None['Traceback (most recent call last):
',' File "test_python.py", line 8, in <module>
s = i.next()
','StopIteration
']
为了捕获“停止迭代”异常并正确中断while循环,我该怎么办?
为什么需要这种东西的一个示例在下面显示为伪代码。
状态机:
s =""whileTrue:if state is STATE_CODE :if"//"in s :
tokens.add( TOKEN_COMMENT, s.split("//")[1])
state = STATE_COMMENTelse:
tokens.add( TOKEN_CODE, s )if state is STATE_COMMENT :if"//"in s :
tokens.append( TOKEN_COMMENT, s.split("//")[1])else
state = STATE_CODE# Re-evaluate same linecontinuetry:
s = i.next()exceptStopIteration:break
I need to emulate a do-while loop in a Python program. Unfortunately, the following straightforward code does not work:
list_of_ints = [ 1, 2, 3 ]
iterator = list_of_ints.__iter__()
element = None
while True:
if element:
print element
try:
element = iterator.next()
except StopIteration:
break
print "done"
Instead of “1,2,3,done”, it prints the following output:
[stdout:]1
[stdout:]2
[stdout:]3
None['Traceback (most recent call last):
', ' File "test_python.py", line 8, in <module>
s = i.next()
', 'StopIteration
']
What can I do in order to catch the ‘stop iteration’ exception and break a while
loop properly?
An example of why such a thing may be needed is shown below as pseudocode.
State machine:
s = ""
while True :
if state is STATE_CODE :
if "//" in s :
tokens.add( TOKEN_COMMENT, s.split( "//" )[1] )
state = STATE_COMMENT
else :
tokens.add( TOKEN_CODE, s )
if state is STATE_COMMENT :
if "//" in s :
tokens.append( TOKEN_COMMENT, s.split( "//" )[1] )
else
state = STATE_CODE
# Re-evaluate same line
continue
try :
s = i.next()
except StopIteration :
break
回答 0
我不确定您要做什么。您可以像这样实现一个do-while循环:
whileTrue:
stuff()if fail_condition:break
要么:
stuff()whilenot fail_condition:
stuff()
您在尝试使用do while循环来打印列表中的内容在做什么?为什么不使用:
for i in l:print iprint"done"
更新:
那你有行列表吗?而您想继续迭代呢?怎么样:
for s in l:whileTrue:
stuff()# use a "break" instead of s = i.next()
看起来像您想要的东西吗?在您的代码示例中,它将是:
for s in some_list:whileTrue:if state is STATE_CODE:if"//"in s:
tokens.add( TOKEN_COMMENT, s.split("//")[1])
state = STATE_COMMENT
else:
tokens.add( TOKEN_CODE, s )if state is STATE_COMMENT:if"//"in s:
tokens.append( TOKEN_COMMENT, s.split("//")[1])break# get next selse:
state = STATE_CODE
# re-evaluate same line# continues automatically
I am not sure what you are trying to do. You can implement a do-while loop like this:
while True:
stuff()
if fail_condition:
break
Or:
stuff()
while not fail_condition:
stuff()
What are you doing trying to use a do while loop to print the stuff in the list? Why not just use:
for i in l:
print i
print "done"
Update:
So do you have a list of lines? And you want to keep iterating through it? How about:
for s in l:
while True:
stuff()
# use a "break" instead of s = i.next()
Does that seem like something close to what you would want? With your code example, it would be:
for s in some_list:
while True:
if state is STATE_CODE:
if "//" in s:
tokens.add( TOKEN_COMMENT, s.split( "//" )[1] )
state = STATE_COMMENT
else :
tokens.add( TOKEN_CODE, s )
if state is STATE_COMMENT:
if "//" in s:
tokens.append( TOKEN_COMMENT, s.split( "//" )[1] )
break # get next s
else:
state = STATE_CODE
# re-evaluate same line
# continues automatically
回答 1
这是一种模拟do-while循环的非常简单的方法:
condition =Truewhile condition:# loop body here
condition = test_loop_condition()# end of loop
Here’s a very simple way to emulate a do-while loop:
condition = True
while condition:
# loop body here
condition = test_loop_condition()
# end of loop
The key features of a do-while loop are that the loop body always executes at least once, and that the condition is evaluated at the bottom of the loop body. The control structure show here accomplishes both of these with no need for exceptions or break statements. It does introduce one extra Boolean variable.
Exception will break the loop, so you might as well handle it outside the loop.
try:
while True:
if s:
print s
s = i.next()
except StopIteration:
pass
I guess that the problem with your code is that behaviour of break inside except is not defined. Generally break goes only one level up, so e.g. break inside try goes directly to finally (if it exists) an out of the try, but not out of the loop.
def do_while(stuff, condition):
while condition(stuff()):
pass
But
1) It’s ugly.
2) Condition should be a function with one parameter, supposed to be filled by stuff (it’s the only reason not to use the classic while loop.)
def coroutine(func):"""Coroutine decorator
Coroutines must be started, advanced to their first "yield" point,
and this decorator does this automatically.
"""def startcr(*ar,**kw):
cr = func(*ar,**kw)
cr.next()return cr
return startcr
@coroutinedef collector(storage):"""Act as "sink" and collect all sent in @storage"""whileTrue:
storage.append((yield))@coroutinedef state_machine(sink):""" .send() new parts to be tokenized by the state machine,
tokens are passed on to @sink
"""
s =""
state = STATE_CODE
whileTrue:if state is STATE_CODE :if"//"in s :
sink.send((TOKEN_COMMENT, s.split("//")[1]))
state = STATE_COMMENT
else:
sink.send(( TOKEN_CODE, s ))if state is STATE_COMMENT :if"//"in s :
sink.send(( TOKEN_COMMENT, s.split("//")[1]))else
state = STATE_CODE
# re-evaluate same linecontinue
s =(yield)
tokens =[]
sm = state_machine(collector(tokens))for piece in i:
sm.send(piece)
Here is a crazier solution of a different pattern — using coroutines. The code is still very similar, but with one important difference; there are no exit conditions at all! The coroutine (chain of coroutines really) just stops when you stop feeding it with data.
def coroutine(func):
"""Coroutine decorator
Coroutines must be started, advanced to their first "yield" point,
and this decorator does this automatically.
"""
def startcr(*ar, **kw):
cr = func(*ar, **kw)
cr.next()
return cr
return startcr
@coroutine
def collector(storage):
"""Act as "sink" and collect all sent in @storage"""
while True:
storage.append((yield))
@coroutine
def state_machine(sink):
""" .send() new parts to be tokenized by the state machine,
tokens are passed on to @sink
"""
s = ""
state = STATE_CODE
while True:
if state is STATE_CODE :
if "//" in s :
sink.send((TOKEN_COMMENT, s.split( "//" )[1] ))
state = STATE_COMMENT
else :
sink.send(( TOKEN_CODE, s ))
if state is STATE_COMMENT :
if "//" in s :
sink.send(( TOKEN_COMMENT, s.split( "//" )[1] ))
else
state = STATE_CODE
# re-evaluate same line
continue
s = (yield)
tokens = []
sm = state_machine(collector(tokens))
for piece in i:
sm.send(piece)
The code above collects all tokens as tuples in tokens and I assume there is no difference between .append() and .add() in the original code.
回答 6
我这样做的方式如下…
condition =Truewhile condition:
do_stuff()
condition =(<something that evaluates to TrueorFalse>)
condition = True
while condition:
do_stuff()
condition = (<something that evaluates to True or False>)
This seems to me to be the simplistic solution, I’m surprised I haven’t seen it here already. This can obviously also be inverted to
while not condition:
etc.
回答 7
做-包含try语句的while循环
loop =Truewhile loop:
generic_stuff()try:
questionable_stuff()# to break from successful completion# loop = False except:
optional_stuff()# to break from unsuccessful completion - # the case referenced in the OP's question
loop =Falsefinally:
more_generic_stuff()
或者,当不需要“ finally”子句时
whileTrue:
generic_stuff()try:
questionable_stuff()# to break from successful completion# break except:
optional_stuff()# to break from unsuccessful completion - # the case referenced in the OP's questionbreak
loop = True
while loop:
generic_stuff()
try:
questionable_stuff()
# to break from successful completion
# loop = False
except:
optional_stuff()
# to break from unsuccessful completion -
# the case referenced in the OP's question
loop = False
finally:
more_generic_stuff()
alternatively, when there’s no need for the ‘finally’ clause
while True:
generic_stuff()
try:
questionable_stuff()
# to break from successful completion
# break
except:
optional_stuff()
# to break from unsuccessful completion -
# the case referenced in the OP's question
break
If you’re in a scenario where you are looping while a resource is unavaliable or something similar that throws an exception, you could use something like
import time
while True:
try:
f = open('some/path', 'r')
except IOError:
print('File could not be read. Retrying in 5 seconds')
time.sleep(5)
else:
break
回答 13
对我来说,典型的while循环将是这样的:
xBool =True# A counter to force a condition (eg. yCount = some integer value)while xBool:# set up the condition (eg. if yCount > 0):(Do something)
yCount = yCount -1else:# (condition is not met, set xBool False)
xBool =False
For me a typical while loop will be something like this:
xBool = True
# A counter to force a condition (eg. yCount = some integer value)
while xBool:
# set up the condition (eg. if yCount > 0):
(Do something)
yCount = yCount - 1
else:
# (condition is not met, set xBool False)
xBool = False
I could include a for..loop within the while loop as well, if situation so warrants, for looping through another set of condition.