我想得到你的设计建议。我有一个控制温度的烤箱,我正在做一些与温度有关的测量。我基本上是设定温度,测量一些东西然后继续前进。
我想出了两个简化的设计,如下所示。第一个使用基于回调的方法:
class Oven(object):
# ... some methods
def step_temperature(start, stop, num, rate, callback):
temperatures = np.linspace(start, stop, num)
for t in temperatures:
self.temperature = t, rate # sweep to temperature with given rate
self._wait_for_stability() # wait until temperature is reached.
callback(t) # execute the measurement
# Use Case
oven = Oven()
oven.step_temperature(start=20, stop=200, num=10, rate=1, callback=measure_stuff)
第二种设计是基于发电机的设计
class Oven(object):
# ... some methods
def step_temperature(start, stop, num, rate):
temperatures = np.linspace(start, stop, num)
for t in temperatures:
self.temperature = t, rate
self._wait_for_stability()
yield t
# Use Case
oven = Oven()
for t in oven.step_temperature(start=20, stop=200, num=10, rate=1):
measure_stuff(t)
我正在倾向于第二种设计,但我对你的建议感兴趣。如果有更好的方法,请不要犹豫告诉我。
答案 0 :(得分:1)
@ P3trus。我最近在StackExchange的CodeReview上回答了一个非常类似的Python“yield vs. callback”问题。如果您想阅读here's a link,但我会总结一下:
有三种常用模式用于解决“报告反馈”要求:
yield
yield
和回调都允许您将UI / IO的表示细节与模型或计算代码分开。这很好。两者都运作良好。
如果你使用Python的yield
,请确保你理解可迭代和生成器,因为有几种语言实现了yield
关键字,但是如果你有例子,那么可能会有一些微妙的实现差异。习惯了C#的yield
。这里是a reference - 它很微妙但值得一读。本质上,在Python函数产生时,它会返回一个生成器,该生成器可以有用地分配给变量,捕获迭代到那一点,但您可能想也可能不希望这样做。不要让那吓到你; yield
很好。
回调确实有一个很好的优势,它们允许返回到调用者(在模型或计算代码中),可用于暂停或停止处理或以其他方式向模型发送消息。这是一个很好的职责分离和,如果你使用yield
,它可以让沟通变得更加困难。或者可能不是。总会有办法的。 :)
例如,在更新报告的温度时,回调还可以监视按钮或键并向调用者返回一个值,这可能表示用户想要中止处理,这不会污染模型特定的UI或IO。
所以不仅仅是:
callback(t)
您可以让callback
执行温度报告工作,但也可以听取用户收集的内容,例如:
if callback(t) == ABORT_BUTTON_PRESSED:
self.shutdown # or whatever
希望这有帮助。
答案 1 :(得分:0)
如果你每次拨打t
偶尔会step_temperature
做不同的事情,(就像你说的那样,以及一些结果,你会做一件事,而另一些你做另一件事) ,你想要发电机版本。如果每次调用step_temperature
,你想要对每个项目做同样的事情,并且之间没有不同的计算,我会使用回调版本。这样,使用您的代码的任何人都不必知道何时调用t
的处理函数。