0

有没有一种方法可以将更多信息返回给实例化生成器函数的调用者,而不仅仅是函数实例本身?

例如,

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),该函数具有计算所需最早数据的逻辑。我希望能够以某种方式将这些信息“它需要的最早数据”返回给调用者。虽然我当然可以让调用者计算并获得相同的信息 - 这是重复的工作并且它并不优雅,因为我想将复杂性封装在生成器函数中。

谢谢

4

2 回答 2

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)
于 2012-04-24T04:19:36.877 回答
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)
于 2012-04-24T03:12:21.417 回答