openYuanrong Generators#

In Python, a function that uses the yield keyword is called a generator. A generator function is a special type of function that can produce results incrementally during iteration, rather than returning all values at once. All generators decorated with yr.instance or yr.invoke are called openYuanrong generators.

Use Cases#

Generators calculate and return only one value per iteration without loading all values into memory at once, effectively saving memory space. Common use cases include:

  • Infinite sequences: Generators can be used to generate infinite sequences without exhausting memory.

  • Data stream processing: Generators can be used to process large data streams, such as reading data line by line from a file or receiving data from a network stream.

Usage Example#

openYuanrong generators return an ObjectRefGenerator object, through which you can call _next and _anext methods, or iterate through it.

Iteration operations may return the following exceptions:

Type

Description

RuntimeError

Failed to get yield return value.

YRInvokeError

Function execution error.

Note

Async generators can only be implemented in stateful functions; stateless functions do not support async.

Stateless Function Generator#

import yr

yr.init()

@yr.invoke
def countdown(n):
    while n > 0:
        yield n
        n -= 1

n = 5
# Use next interface
generator = countdown.invoke(n)
print(yr.get(next(generator)))

# Use for loop
for ref in generator:
    print(yr.get(ref))

yr.finalize()

Stateful Function Generator#

import yr

yr.init()

@yr.instance
class StatefulFunc():
    def __init__(self, number):
        self.sum = number

    def countdown(self):
        n = self.sum
        while n > 0:
            yield n
            n -= 1

n = 5
instance = StatefulFunc.invoke(n)

# Use next interface
generator = instance.countdown.invoke()
print(yr.get(next(generator)))

# Use for loop
for ref in generator:
    print(yr.get(ref))

instance.terminate()
yr.finalize()

Stateful Function Async Generator#

import asyncio
import time
import yr

yr.init()

@yr.instance
class StatefulFunc():
    async def gen(self, n):
        for i in range(n):
            await asyncio.sleep(1)
            yield i

instance = StatefulFunc.invoke()

async def async_gen(n):
    gen = instance.gen.invoke(n)
    async for ref in gen:
        res = await ref
        print(res)

async def multi_gen():
    n = 5
    await asyncio.gather(async_gen(n), async_gen(n), async_gen(n), async_gen(n), async_gen(n))

now = time.time()
asyncio.run(multi_gen())
cost = time.time() - now
# Concurrently execute 5 generator functions, each taking 5s, total time less than 6s
print(cost)

instance.terminate()
yr.finalize()