从函数创建生成器 [英] creating generators from function

查看:84
本文介绍了从函数创建生成器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用coroutine / generator框架来模拟并发进程。


为此,我使用一般表单编写所有函数:


而True:

做东西

产量无


使这些生成器功能与标准线程兼容

界面,我试图写一个装饰器,它将一个标准的

函数转换成一个生成器函数(下面附带的代码)。

不幸的是,我收到了一个例外,我可以测试一下我的想法是否可以工作:


TypeError:无法创建''generator''实例


我想我可以走另一条路,并将发电机转换为

功能,但这似乎并不合适。


有没有解决所描述的问题?


Sw。

来自操作码导入opmap

导入类型

globals()。update(opmap)

def generatorize (f):

co = f.func_code

nc = [orc(x)for x in co.co_code]

for op,我在枚举(nc):

如果op == RETURN_VALUE:

nc [i] = YIELD_VALUE

newcode =''''。 join([chr(x)for x in nc])

codeobj = type(co)(co.co_argcount,co.co_nlocals,co.co_stacksize,

co。 co_flags,newcode,co.co_consts,co.co_names,

co.co_varnames,co.co_filename,co.co_name,

co.co_firstlineno,co.co_lnotab,co。 co_freevars,

co.co_cellvars)


print types.GeneratorType(f)(codeobj,f.func_globals,f.func_name,

f.func_defaults,f.func_closure)

返回f

@generatorize

def f():

而True:

返回1


def g():

而True:

收益率1


打印g()

打印f()

解决方案

Simon Wittber写道:

我用用于模拟并发进程的协同程序/生成器框架。

为此,我使用一般形式编写所有函数:

而True:
做东西<产品无

为了使这些生成器功能与标准线程接口兼容,我尝试编写一个装饰器,将标准
函数转换为生成器函数(代码附在下面)。
[snip] @generatorize
def f():
而True:
返回1

def g():
而True :
产量1

打印g()
打印f()




我有点困惑你想在这里做什么f()

函数,特别是没有多大意义 - ''真实''

自从没有做任何事情通过循环第一次执行'return 1''

。如果你真的想把你的功能变成

形式的生成器:


而True:

做东西

收益无


为什么你不能这样做:

< blockquote class =post_quotes> def generatorize(f):
.... def new_f(* args,** kwds):

.... while True:

.... f(* args,** kwds)

....收益无

....返回new_f

.... @generatorize
.... def f():

....返回1

....我= f()
打印i.next()
无打印i.next()






基本上,我认为''做东西''的功能是'

包裹。


Steve


Simon Wittber写道:

我使用了一个协程/发电机框架ork用于模拟并发进程。

要做到这一点,我使用一般形式编写所有函数:

而True:
做*东西
产量*无

为了使这些生成器功能与标准线程接口兼容,我尝试编写一个装饰器,将标准
函数转换为生成器函数(下面附带的代码) )。
不幸的是,在我测试我的想法是否有效之前我收到了一个例外:

TypeError:无法创建''generator''实例

我想我可以走另一条路,并将发电机转换成
功能,但这似乎并不合适。

无论如何解决所描述的问题?




生成器只是设置了额外标志的函数。我尝试了以下

修改你的代码:


< code>

来自操作码导入opmap

globals()。update(opmap)

def _f():传递

function = type(_f)

del _f

def generatorize(f):

co = f.func_code

nc = [ord(x)for x in co.co_code]

for i,op in enumerate(nc [: - 1]):

如果op == RETURN_VALUE:

nc [i] = YIELD_VALUE

newcode =''''。join([chc(x)for x in nc])


codeobj = type (co)(co.co_argcount,co.co_nlocals,co.co_stacksize,

co.co_flags + 32,newcode,co.co_consts,

co.co_names,

co.co_varnames,co.co_filename,co.co_name,

co.co_firstlineno,co.co_lnotab,co.co_freevars,

co.co_cellvars)


返回函数(codeobj,f.func_globals,f.func_name,

f.func_defaults,f.func_closure)


@generatorize

def f():

而True:

返回1


def g():

而True:

收益率1


打印g()

打印f()


import itertools

打印列表(itertools.islice(f(),5))

< / code>


最困难的部分是找到enumerate()错误。我同意史蒂文的说法

在函数和生成器之间进行转换,通过用yield替换返回值

,反之亦然,几乎没用。


彼得




>我对你在这里想做什么感到有点困惑。 f()

函数,特别是没有多大意义




我看到我被误解了。这个例子是设计的,似乎是不正确的。


我使用生成器函数和调度程序模拟线程。


我的实现在这里生活: http://metaplay.com.au/svn/LGT /LGT/nanothreads.py


如果在普通线程中运行相同的函数,它们将需要永远循环,而不是
每次迭代时产生无。我现在看到

现在用产量替换回报不起作用,收益指令

需要插入某处。


我想这会改变我的问题:我可以将一个包含无限循环的函数转换成一个生成器,它将在每个

迭代中产生吗?


Sw。


I use a coroutine/generator framework for simulating concurrent processes.

To do this, I write all my functions using the general form:

while True:
do stuff
yield None

To make these generator functions compatible with a standard thread
interface, I attempted to write a decorator which converts a standard
function into a generator function (code attached below).
Unfortunately, I received an exception, before I could test if my idea
would work:

TypeError: cannot create ''generator'' instances

I guess I can go the other way, and convert a generator into a
function, but that just doesn''t seem right.

Is there anyway solve the problem described?

Sw.
from opcode import opmap
import types
globals().update(opmap)

def generatorize(f):
co = f.func_code
nc = [ord(x) for x in co.co_code]
for op,i in enumerate(nc):
if op == RETURN_VALUE:
nc[i] = YIELD_VALUE
newcode = ''''.join([chr(x) for x in nc])
codeobj = type(co)(co.co_argcount, co.co_nlocals, co.co_stacksize,
co.co_flags, newcode, co.co_consts, co.co_names,
co.co_varnames, co.co_filename, co.co_name,
co.co_firstlineno, co.co_lnotab, co.co_freevars,
co.co_cellvars)

print types.GeneratorType(f)(codeobj, f.func_globals, f.func_name,
f.func_defaults, f.func_closure)
return f

@generatorize
def f():
while True:
return 1

def g():
while True:
yield 1

print g()
print f()

解决方案

Simon Wittber wrote:

I use a coroutine/generator framework for simulating concurrent processes.

To do this, I write all my functions using the general form:

while True:
do stuff
yield None

To make these generator functions compatible with a standard thread
interface, I attempted to write a decorator which converts a standard
function into a generator function (code attached below). [snip] @generatorize
def f():
while True:
return 1

def g():
while True:
yield 1

print g()
print f()



I''m a little confused as to what you''re trying to do here. The f()
function, in particular, doesn''t make much sense -- the ''while True''
doesn''t do anything since the ''return 1'' is executed on the first time
through the loop. If you really do want to turn your functions into
generators of the form:

while True:
do stuff
yield None

why can''t you just do:

def generatorize(f): .... def new_f(*args, **kwds):
.... while True:
.... f(*args, **kwds)
.... yield None
.... return new_f
.... @generatorize .... def f():
.... return 1
.... i = f()
print i.next() None print i.next()


None

Basically, I''ve assumed that ''do stuff'' is the function that''s being
wrapped.

Steve


Simon Wittber wrote:

I use a coroutine/generator framework for simulating concurrent processes.

To do this, I write all my functions using the general form:

while True:
do*stuff
yield*None

To make these generator functions compatible with a standard thread
interface, I attempted to write a decorator which converts a standard
function into a generator function (code attached below).
Unfortunately, I received an exception, before I could test if my idea
would work:

TypeError: cannot create ''generator'' instances

I guess I can go the other way, and convert a generator into a
function, but that just doesn''t seem right.

Is there anyway solve the problem described?



Generators are just functions with an extra flag set. I tried the following
modification of your code:

<code>
from opcode import opmap
globals().update(opmap)

def _f(): pass
function = type(_f)
del _f

def generatorize(f):
co = f.func_code
nc = [ord(x) for x in co.co_code]
for i, op in enumerate(nc[:-1]):
if op == RETURN_VALUE:
nc[i] = YIELD_VALUE
newcode = ''''.join([chr(x) for x in nc])

codeobj = type(co)(co.co_argcount, co.co_nlocals, co.co_stacksize,
co.co_flags + 32, newcode, co.co_consts,
co.co_names,
co.co_varnames, co.co_filename, co.co_name,
co.co_firstlineno, co.co_lnotab, co.co_freevars,
co.co_cellvars)

return function(codeobj, f.func_globals, f.func_name,
f.func_defaults, f.func_closure)

@generatorize
def f():
while True:
return 1

def g():
while True:
yield 1

print g()
print f()

import itertools
print list(itertools.islice(f(), 5))
</code>

The hardest part was to find the enumerate() bug. I agree with Steven that
converting between functions and generators by replacing return with yield
and vice versa is hardly ever useful, though.

Peter





> I''m a little confused as to what you''re trying to do here. The f()

function, in particular, doesn''t make much sense



I see I am misunderstood. The example was contrived, and it seems, incorrect.

I simulate threads, using generator functions and a scheduler.

My implementation lives here: http://metaplay.com.au/svn/LGT/LGT/nanothreads.py

If the same functions were to run inside a normal thread, they would
need to loop forever, rather than yield None on each iteration. I see
now that replacing return with yield won''t work, a yield instruction
needs to be inserted somewhere.

I guess this changes my question to: Can I convert a function
containing an infinite loop, into a generator which will yield on each
iteration?

Sw.


这篇关于从函数创建生成器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆