Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何判断发电机是否刚刚启动?_Python_Generator_Yield - Fatal编程技术网

Python 如何判断发电机是否刚刚启动?

Python 如何判断发电机是否刚刚启动?,python,generator,yield,Python,Generator,Yield,我想要一个函数,刚刚启动,其行为如下: >>> def gen(): yield 0; yield 1 >>> a = gen() >>> is_just_started(a) True >>> next(a) 0 >>> is_just_started(a) False >>> next(a) 1 >>> is_just_started(a) False >

我想要一个函数,
刚刚启动,其行为如下:

>>> def gen(): yield 0; yield 1
>>> a = gen()
>>> is_just_started(a) 
True
>>> next(a)
0
>>> is_just_started(a) 
False
>>> next(a)
1
>>> is_just_started(a) 
False
>>> next(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> is_just_started(a)
False

然而,这似乎令人憎恶

您可以创建迭代器,并将标志设置为迭代器类的实例属性,如下所示:

class gen(object):
    def __init__(self, n):
        self.n = n
        self.num, self.nums = 0, []
        self.is_just_started = True  # Your flag

    def __iter__(self):
        return self

    # Python 3 compatibility
    def __next__(self):
        return self.next()

    def next(self):
        self.is_just_started = False  # Reset flag with next
        if self.num < self.n:
            cur, self.num = self.num, self.num+1
            return cur
        else:
            raise StopIteration()
样本运行:

>>> a = gen(2)

>>> is_just_started(a)
True

>>> next(a)
0
>>> is_just_started(a)
False

>>> next(a)
1
>>> is_just_started(a)
False

>>> next(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 19, in next
StopIteration
>a=gen(2)
>>>刚刚开始吗(a)
真的
>>>下一(a)
0
>>>刚刚开始吗(a)
假的
>>>下一(a)
1.
>>>刚刚开始吗(a)
假的
>>>下一(a)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第19行,下一页
停止迭代

要了解迭代器和生成器之间的区别,请选中“创建一个新的生成器”,它只从您感兴趣的生成器中生成一旦第一个值被使用,它就会设置一个标志。之后,它可以简单地对其余项目使用
收益率

使用替代发电机作为您感兴趣的发电机的替代品,以监控“正在启动”状态


这种技术是非侵入性的,甚至可以在您无法控制源代码的生成器上使用

这仅适用于Python 3.2+:

>>> def gen(): yield 0; yield 1
... 
>>> a = gen()
>>> import inspect
>>> inspect.getgeneratorstate(a)
'GEN_CREATED'
>>> next(a)
0
>>> inspect.getgeneratorstate(a)
'GEN_SUSPENDED'
>>> next(a)
1
>>> inspect.getgeneratorstate(a)
'GEN_SUSPENDED'
>>> next(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> inspect.getgeneratorstate(a)
'GEN_CLOSED'
出于好奇,我调查了CPython,想弄清楚它是如何决定这一点的。。。显然,它关注的是
generator.gi_frame.f_lasti
,它是“字节码中最后尝试的指令的索引”。如果它是
-1
,那么它还没有启动

以下是py2版本:

def is_just_started(gen):
    return gen.gi_frame is not None and gen.gi_frame.f_lasti == -1

是否允许在发电机内部进行修改?允许它装饰它吗?它看起来像是
gi_running
表明解释器实际上正在运行代码,所以在迭代之间它是假的。这可能是重复的,这就是我喜欢stackoverflow的原因。更好的是,它看起来是这样的。
GEN\u运行有什么好处?医生说“如果它目前正在由翻译执行”,但我认为这是荒谬的,因为吉尔?@cat的措辞有点奇怪。发电机可能正在运行,但被IO阻塞(例如)。我怀疑,如果发电机在执行中,但调度程序延迟,它也会发生。@猫:也许你在发电机中。它还将是在其他线程中运行的生成器的状态,无论这些线程是否被GIL阻塞。@cat:
def g():yield inspect.getgeneratorstate(x)
x=g();下一步(x)
那不是发电机。@wim:确实是这样。对不起,我的术语类生成器,正确的单词应该是迭代器。更新的答案。这种技术的优点是它可以在所有Python版本上工作——例如,包括Pypy。
>>> def gen(): yield 0; yield 1
... 
>>> a = gen()
>>> import inspect
>>> inspect.getgeneratorstate(a)
'GEN_CREATED'
>>> next(a)
0
>>> inspect.getgeneratorstate(a)
'GEN_SUSPENDED'
>>> next(a)
1
>>> inspect.getgeneratorstate(a)
'GEN_SUSPENDED'
>>> next(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> inspect.getgeneratorstate(a)
'GEN_CLOSED'
import inspect

def is_just_started(gen):
    return inspect.getgeneratorstate(gen) == inspect.GEN_CREATED:
def is_just_started(gen):
    return gen.gi_frame is not None and gen.gi_frame.f_lasti == -1