cls*_*udt 3 python oop separation-of-concerns
假设我想使用进度条打印机跟踪循环的进度ProgressMeter(如本配方中所述).
def bigIteration(collection):
for element in collection:
doWork(element)
Run Code Online (Sandbox Code Playgroud)
我希望能够打开和关闭进度条.出于性能原因,我还想每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)
Run Code Online (Sandbox Code Playgroud)
但是,我不满意.从"审美"的角度来看,循环的功能代码现在被"污染"了一般的进度跟踪代码.
您能想到一种清晰地分离进度跟踪代码和功能代码的方法吗?(可以有进度跟踪装饰器吗?)
看起来这个代码将受益于null对象模式.
# a progress bar that uses ProgressMeter
class RealProgressBar:
pm = Nothing
def setMaximum(self, max):
pm = progress.ProgressMeter(total=max)
pc = 0
def progress(self):
pc += 1
if pc % 100 = 0:
pm.update(pc)
# a fake progress bar that does nothing
class NoProgressBar:
def setMaximum(self, max):
pass
def progress(self):
pass
# Iterate with a given progress bar
def bigIteration(collection, progressBar=NoProgressBar()):
progressBar.setMaximum(len(collection))
for element in collection:
progressBar.progress()
doWork(element)
bigIteration(collection, RealProgressBar())
Run Code Online (Sandbox Code Playgroud)
(原谅我的法语,呃,Python,这不是我的母语;)希望你能得到这个想法.)
这使您可以从循环中移动进度更新逻辑,但是仍然有一些与进度相关的调用.
如果从集合中创建生成器,可以在迭代时自动跟踪进度,则可以删除此部件.
# turn a collection into one that shows progress when iterated
def withProgress(collection, progressBar=NoProgressBar()):
progressBar.setMaximum(len(collection))
for element in collection:
progressBar.progress();
yield element
# simple iteration function
def bigIteration(collection):
for element in collection:
doWork(element)
# let's iterate with progress reports
bigIteration(withProgress(collection, RealProgressBar()))
Run Code Online (Sandbox Code Playgroud)
这种方法使您的bigIteration功能保持原样并且具有高度可组合性.例如,假设你也想要添加取消你的这个大的迭代.只需创建一个恰好可以取消的另一个生成器.
# highly simplified cancellation token
# probably needs synchronization
class CancellationToken:
cancelled = False
def isCancelled(self):
return cancelled
def cancel(self):
cancelled = True
# iterates a collection with cancellation support
def withCancellation(collection, cancelToken):
for element in collection:
if cancelToken.isCancelled():
break
yield element
progressCollection = withProgress(collection, RealProgressBar())
cancellableCollection = withCancellation(progressCollection, cancelToken)
bigIteration(cancellableCollection)
# meanwhile, on another thread...
cancelToken.cancel()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1029 次 |
| 最近记录: |