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