[英]callback vs generator based design
I'd like to get your advice for a design. 我想获得您的设计建议。 I've got an Oven controlling the temperature and I'm doing some temperature dependent measurements.
我有一个烤箱控制温度,并且正在执行一些温度相关的测量。 I'm basically setting the temperature, measure some stuff and move on.
我基本上是在设定温度,测量一些东西然后继续前进。
I came up with two designs, simplified of course, which are shown below. 我想出了两种设计,它们当然经过了简化,如下所示。 The first one uses a callback based approach:
第一个使用基于回调的方法:
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)
The second design is a generator based design 第二种设计是基于发电机的设计
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)
I'm tending towards the second design, but I'm interrested in your suggestions. 我正在尝试第二个设计,但是我对您的建议很感兴趣。 If there is a even better way don't hesitate to tell me.
如果有更好的方法,请随时告诉我。
@P3trus. @ P3trus。 I recently answered a very similar Python "yield versus callback" question on StackExchange's CodeReview.
我最近在StackExchange的CodeReview上回答了一个非常类似的Python“收益与回调”问题。 If you want to read it, here's a link but I'll summarize:
如果您想阅读, 这里是一个链接,但我总结一下:
There are three common patterns used to solve the "report feedback" requirement: 有三种常见的模式可用来解决“报告反馈”的要求:
yield
Both yield
and callbacks allow you to separate the presentation details of UI/IO from the model or computation code. yield
和回调都允许您将UI / IO的表示详细信息与模型或计算代码分开。 This is good. 很好 Both work well.
两者都运作良好。
If you go with Python's yield
, ensure you understand iterables and generators well, since several languages implement a yield
keyword but have subtle implementation differences that might surprise you if, for example, you're used to C#'s yield
. 如果您使用Python的
yield
,请确保您很好地理解了可迭代对象和生成器,因为多种语言实现了yield
关键字,但实现方面的细微差别可能会使您感到惊讶,例如,如果您习惯于C#的yield
。 Here's a reference on that -- it's subtle but worth reading. 这是一个参考 ,虽然有些微妙但值得一读。 Essentially, in Python when your function yields, it returns a generator which can be usefully assigned to a variable, capturing iteration to that point, but you may or may not want to do that.
本质上,在Python中,当函数产生时,它会返回一个生成器,该生成器可以有效地分配给变量,从而捕获到该点的迭代,但是您可能想要也可能不想这样做。 Don't let that scare you;
不要让那吓到你;
yield
is good. yield
好。
Callbacks do have a nice advantage in that they allow communication back to the caller (in the model or computational code) which can be used to pause or halt processing or otherwise send a message to the model. 回调确实有一个很好的优点,因为它们允许通信返回给调用者(在模型或计算程序),它可以用来暂停或停止处理或以其他方式将消息发送到模型。 This is a nice separation of duties and it allows communication that may be more difficult if you use
yield
. 这是很好的职责分离,如果您使用
yield
,则允许进行交流可能会更加困难。 Or maybe not. 或者可能不是。 There is always a way.
总会有办法的。 :)
:)
For example, while updating the reported temperature the callback can also monitor buttons or keys and return a value to the caller which could indicate, for example, that the user wants to abort processing and this doesn't pollute the model with awareness of specific UI or IO. 例如,在更新报告的温度时,回调还可以监视按钮或按键,并向调用方返回一个值,该值可以指示例如用户想要中止处理,并且这不会污染具有特定UI的模型。或IO。
So instead of just: 因此,不仅仅是:
callback(t)
You can let callback
do its temperature reporting job but also listen to what it may have collected from the user, such as: 您可以让
callback
执行其温度报告工作,还可以侦听它可能从用户那里收集的内容,例如:
if callback(t) == ABORT_BUTTON_PRESSED:
self.shutdown # or whatever
Hope this helps. 希望这可以帮助。
If you occasionally do different stuff with t
per call of step_temperature
, (like, you call it, and some of the results, you do one thing with, while some you do another with), you'd want the generator version. 如果您偶尔会在每次调用
step_temperature
用t
做不同的事情(例如,您调用它,并且在某些结果中,您使用一件事,而在另一些结果中使用另一件事),则需要生成器版本。 If every time you call step_temperature
, you want the same thing done to every item, and no differing computation between, I'd use the callback version. 如果每次调用
step_temperature
,都希望对每个项目执行相同的操作,并且两者之间没有不同的计算,那么我将使用回调版本。 That way anyone who uses your code doesn't have to know when to call their processing function for t
. 这样,使用您的代码的任何人都不必知道何时为
t
调用其处理函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.