分离进度跟踪和循环逻辑
假设我想使用进度条打印机 ProgressMeter
跟踪循环的进度(如本 食谱)。
def bigIteration(collection):
for element in collection:
doWork(element)
我希望能够打开和关闭进度条。出于性能原因,我还想每 x 步更新一次。我的天真做法是
def bigIteration(collection, progressbar=True):
if progressBar:
pm = progress.ProgressMeter(total=len(collection))
pc = 0
for element in collection:
if progressBar:
pc += 1
if pc % 100 = 0:
pm.update(pc)
doWork(element)
然而,我不满意。从“美学”的角度来看,循环的功能代码现在被通用进度跟踪代码“污染”。
您能想出一种方法来干净地分离进度跟踪代码和功能代码吗? (可以有进度跟踪装饰器之类的吗?)
Suppose i want to track the progress of a loop using the progress bar printer ProgressMeter
(as described in this recipe).
def bigIteration(collection):
for element in collection:
doWork(element)
I would like to be able to switch the progress bar on and off. I also want to update it only every x steps for performance reasons. My naive way to do this is
def bigIteration(collection, progressbar=True):
if progressBar:
pm = progress.ProgressMeter(total=len(collection))
pc = 0
for element in collection:
if progressBar:
pc += 1
if pc % 100 = 0:
pm.update(pc)
doWork(element)
However, I am not satisfied. From an "aesthetic" point of view, the functional code of the loop is now "contaminated" with generic progress-tracking code.
Can you think of a way to cleanly separate progress-tracking code and functional code? (Can there be a progress-tracking decorator or something?)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
看起来这段代码会受益于空对象模式。
(请原谅我的法语,呃,Python,这不是我的母语;)希望您明白这个想法。)
这可以让您将进度更新逻辑从循环中移出,但其中仍然有一些与进度相关的调用。
如果您从集合中创建一个生成器,该生成器在迭代时自动跟踪进度,则可以删除此部分。
这种方法使您的 bigIteration 函数保持原样,并且具有高度可组合性。例如,假设您还想在您的这个大迭代中添加取消功能。只需创建另一个恰好可以取消的生成器即可。
It seems like this code would benefit from the null object pattern.
(Pardon my French, er, Python, it's not my native language ;) Hope you get the idea, though.)
This lets you move the progress update logic from the loop, but you still have some progress related calls in there.
You can remove this part if you create a generator from the collection that automatically tracks progress as you iterate it.
This approach leaves your
bigIteration
function as is and is highly composable. For example, let's say you also want to add cancellation this big iteration of yours. Just create another generator that happens to be cancellable.您可以将 bigIteration 重写为生成器函数,如下所示:
然后,您可以在此之外做很多事情:
You could rewrite
bigIteration
as a generator function as follows:Then, you could do a great deal outside of this:
我的方法是这样的:
每当它发生变化时(或者每当它想要报告它时),循环代码就会产生进度百分比。然后,进度跟踪代码从生成器中读取数据,直到它为空为止;每次阅读后更新进度条。
然而,这也有一些缺点:
My approach would be like that:
The looping code yields the progress percentage whenever it changes (or whenever it wants to report it). The progress-tracking code then reads from the generator until it's empty; updating the progress bar after every read.
However, this also has some disadvantages: