我想听听您对设计的建议。我有一个控制温度的 toastr ,我正在做一些与温度相关的测量。我基本上是设置温度,测量一些东西然后继续。
我想出了两种设计,当然是简化的,如下所示。第一个使用基于回调的方法:
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)
我倾向于第二种设计,但我对你的建议很感兴趣。如果有更好的方法请不要犹豫告诉我。
最佳答案
@P3trus。我最近在 StackExchange 的 CodeReview 上回答了一个非常类似的 Python“yield 与回调”问题。如果您想阅读,here's a link但我总结一下:
解决“报告反馈”需求的常见模式有以下三种:
产量
- 回调函数
- 内联、硬编码的反馈
yield 和回调都允许您将 UI/IO 的表示细节与模型或计算代码分开。这很好。两者都运作良好。
如果您使用 Python 的 yield
,请确保您很好地理解迭代器和生成器,因为有几种语言实现了 yield
关键字,但存在细微的实现差异,如果出现以下情况,这些差异可能会让您感到惊讶:例如,您已经习惯了 C# 的 yield
。这是a reference关于这一点——它很微妙,但值得一读。本质上,在Python中,当你的函数产生时,它会返回一个生成器,它可以有用分配给一个变量,捕获到该点的迭代,但你可能想也可能不想这样做。不要让这吓到你; 产量
很好。
回调确实有一个很好的优势,因为它们允许与调用者(在模型或计算代码中)进行通信,可用于暂停或停止处理或以其他方式向模型发送消息。这是一个很好的职责分离并且它允许通信,如果您使用yield
,通信可能会更加困难。或者可能不是。天无绝人之路。 :)
例如,在更新报告的温度时,回调还可以监视按钮或按键并向调用者返回一个值,该值可以指示用户想要中止处理,并且这不会污染模型的意识特定的 UI 或 IO。
所以不仅仅是:
callback(t)
您可以让 callback
完成其温度报告工作,但也可以监听它从用户那里收集的信息,例如:
if callback(t) == ABORT_BUTTON_PRESSED:
self.shutdown # or whatever
希望这有帮助。
关于python - 回调与基于生成器的设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19845101/