![](/img/trans.png)
[英]Discord.py(v 1.5.0) : TypeError: can't send non-None value to a just-started generator
[英]How can I tell whether a generator was just-started?
我想要一個函數is_just_started
,其行為類似於以下內容:
>>> 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
我該如何實現這個功能?
我查看了.gi_running
屬性,但它似乎用於其他東西。
如果我知道需要發送到生成器的第一個值,我可以這樣做:
def safe_send(gen, a):
try:
return gen.send(a)
except TypeError as e:
if "just-started" in e.args[0]:
gen.send(None)
return gen.send(a)
else:
raise
然而,這似乎令人憎惡。
這僅適用於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'
因此,請求的功能是:
import inspect
def is_just_started(gen):
return inspect.getgeneratorstate(gen) == inspect.GEN_CREATED:
出於好奇,我調查了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
制造一台新的發電機,只需從您感興趣的發電機中產生。 一旦消耗了第一個值,它就會設置一個標志 。 之后,它可以簡單地使用其他項目的yield from
。
使用替代生成器代替您有興趣監視“is_just_started”狀態的生成器。
此技術是非侵入式的,甚至可以在您無法控制源代碼的生成器上使用。
您可以創建一個迭代器並將標志作為實例屬性設置為迭代器類,如下所示:
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()
你的價值檢查功能如下:
def is_just_started(my_generator):
return my_generator.is_just_started
樣品運行:
>>> 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
要了解迭代器和生成器之間的區別,請檢查Python的生成器和迭代器之間的差異
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.