在Python生成器里面有没有类似“self”的东西?

问题描述:

有什么方法可以在生成器的定义中获取对返回的生成器对象的引用吗?这将类似于self参数传递给迭代器的__next__方法中的方法。浏览Python的文档后,我还没有发现任何类似的东西。在Python生成器里面有没有类似“self”的东西?

这个问题出现在我正在探索如何使用生成器作为协同程序的情况下,我可以在Python中实现以下大部分想法。 Paper:http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.19.79

我能做的最接近的是以下内容,使用装饰器,它基于David Beazley的装饰器coroutine,但感觉有点像黑客。

from functools import wraps 


def coroutine(func): 
    @wraps(func) 
    def decorated(*args, **kwargs): 
     f = func(*args, **kwargs) 
     next(f) 
     f.send(f) 
     return f 
    return decorated 


@coroutine 
def A(): 
    self = yield 
    # do stuff... 

编辑:下面的类,基于下面的答案,可以用作装饰器具有所述发电机接收到self参考作为其第一个参数中。它具有额外的好处,任何装饰它的发电机将具有类型coroutine

class coroutine(object): 
    """Decorator class for coroutines with a self parameter.""" 
    def __new__(cls, func): 
     @wraps(func) 
     def decorated(*args, **kwargs): 
      o = object.__new__(cls) 
      o.__init__(func, args, kwargs) 
      return o 
     return decorated 

    def __init__(self, generator, args, kw): 
     self.generator = generator(self, *args, **kw) 
     next(self.generator) 

    def __iter__(self): 
     return self 

    def __next__(self): 
     return next(self.generator) 

    next = __next__ 

    def send(self, value): 
     return self.generator.send(value) 


# Usage: 

@coroutine 
def A(self): 
    while True: 
     message = yield 
     print self is message 


a = A() 
b = A() 
a.send(a) # outputs True 
a.send(b) # outputs False 
+0

我已经简要地浏览了大约三分之一的论文,并且我没有看到任何您希望协程的参考文献。不过,看起来你希望协程能够在任何给定的索引下触发协程。这是准确的,还是应该回去实际阅读报纸而不是撇号? – user2357112

+1

如果你确实需要一个协程来引用它,你会用它来做什么?协程会将其自身作为回调代码的其他部分吗? – user2357112

+1

你可以把一些用过的案例,其实我不清楚你想做什么。 –

这是一个使用代理的建议。

def selfDecorator(func): 
    def wrap(*args, **kw): 
     return SelfGenerator(func, args, kw) 
    return wrap 

class SelfGenerator(object): 
    """This class implements the generator interface""" 
    def __init__(self, generator, args, kw): 
     self.generator = generator(self, *args, **kw) 
    def __iter__(self): 
     return self 
    def __next__(self): 
     return next(self.generator) 
    next = __next__ 
    def send(self, value): 
     return self.generator.send(value) 

@selfDecorator 
def gen(self, x): # your generator function with self 
    for i in range(x): 
     yield self 


for x in gen(5): 
    print x # prints <__main__.SelfGenerator object at 0x02BB16D0> 

由于SelfGenerator是代理到原来的发电机它具有相同的接口和蟒蛇自己的发电机可以完全使用。

先回答

不能调用本身就是一个发电机:

>>> def generator(): 
    for value in g: 
     yield value 


>>> g = generator() 
>>> next(g) 

Traceback (most recent call last): 
    File "<pyshell#13>", line 1, in <module> 
    next(g) 
    File "<pyshell#11>", line 2, in generator 
    for value in g: 
ValueError: generator already executing 

猜测:在纸张上的自我可能并不意味着发电机本身,而是一个对象,一些状态保持,也许在一些发电机之间共享。

更确切地说,约束的有向图在被视为无向图时要求无周期。

这让我觉得生成器并没有引用它的'相同'执行。为什么它应该通过迭代获得自己的价值?它可以使用局部变量。

协程起源于Simula。也许要了解自我是什么,你可以看看语言。

+0

你有引用“来自Simula的Coroutines”吗?*上相关页面的快速扫描显然是不明确的; Simula可能只是早期的采用者。 (非常早期的采用者。) –

+0

不,我没有引用。在阅读关于面向对象历史的东西时,这成为我的知识。据我所知,它是第一个采用者。 (=起源)也许是第一个成功的采用者。我写这篇文章是因为我不确定撒手与“自我”的含义。一个指向自己的运行中的发生器对我来说毫无意义。 – User

+0

我刚问过,因为我很好奇,并且因为WP的快速扫描并不清楚。 (我不在工作中,所以我不能直接阅读那些遥远的文献)。我发现很有趣的是,coros是一个很长时间不受欢迎的功能,然而近年来这种功能已经开始复兴。 –