有没有一种方法可以向实例化生成器函数的调用者返回更多信息,而不仅仅是函数实例本身?
例如,
def genFn(a, b, c):
# some initialisation / pre-computation
startPt = fn(a, b, c)
data = (yield None)
while True:
# perform some computation
data = (yield result)
f = genFn(5, 6, 7)
start = f.get("startPt") # this line syntax is wrong - just to show what I want
f.send(None)
for data in dataseries[startPt:]:
k = f.send(data)
...
基于传入的参数(a,b,c),该函数具有计算其所需的最早数据的逻辑。我喜欢以某种方式将这些信息“它需要的最早数据”返回给调用者。虽然我当然可以让调用者计算并获得相同的信息 - 这是一种重复工作,但它并不优雅,因为我想在生成器函数中封装复杂性。
由于
Ť
答案 0 :(得分:1)
您可以将其作为第一个send
来电的当前未使用的返回值返回。
def genFn(a, b, c):
# some initialisation / pre-computation
startPt = fn(a, b, c)
data = (yield startPt)
while True:
# perform some computation
data = (yield result)
f = genFn(5, 6, 7)
startPt = f.send(None) # first yield returns the start point
for data in dataseries[startPt:]:
k = f.send(data)
顺便说一下,.send(None)
与.next()
相同。
或者您可以使用类并使用生成器作为其方法之一。预计算将在__init__
中完成,数据可以通过实例属性进行访问。
class GenCl(object):
def __init__(self, a, b, c):
self.startPt = fn(a, b, c)
def gen(self):
startPt = self.startPt # get the startPt calculated in __init__
data = (yield None)
while True:
# perform some computation
data = (yield result)
o = genCl(5, 6, 7)
startPt = o.startPt
f = o.gen() # create the generator object
f.send(None)
for data in dataseries[startPt:]:
k = f.send(data)
另一个想法是使用闭包。函数调用将返回生成器和起始点,例如在元组中。
def genFn(a, b, c):
# some initialisation / pre-computation
startPt = fn(a, b, c)
def gen(): # actual generator function
data = (yield None)
while True:
# perform some computation
data = (yield result)
return gen(), startPt # returns generator and startPt
f, startPt = genFn(5, 6, 7)
f.send(None)
for data in dataseries[startPt:]:
k = f.send(data)
答案 1 :(得分:0)
您可以创建一个特殊的类,可以将其发送到生成器以使其返回您的特殊值。
class GetStartPt:
pass
def genFn(a, b, c):
startPt = fn(a, b, c)
data = (yield None)
while True:
if data is GetStartPt:
data = (yield startPt)
continue
# compute here
data = (yield result)
f = genFn(5, 6, 7)
f.send(GetStartPt)
但是,你可能最好为此编写一个包装类:
class GenClass(object):
def __init__(self, a, b, c):
self.startPt = fn(a, b, c)
def generator(startPt, a, b c):
data = (yield None)
while True:
# compute here
data = (yield result)
self._generator = generator(self.startPt, a, b, c)
def __iter__(self):
return self._generator
def next(self):
return self._generator.next()
def send(self, value):
return self.generator.send(value)