何为使用yield
Python 中的关键字?
比如说,我在试着理解这个代码1:
def _get_child_candidates(self, distance, min_dist, max_dist):
if self._leftchild and distance - max_dist < self._median:
yield self._leftchild
if self._rightchild and distance + max_dist >= self._median:
yield self._rightchild
这就是打电话的人:
result, candidates = [], [self]
while candidates:
node = candidates.pop()
distance = node._get_dist(obj)
if distance <= max_dist and distance >= min_dist:
result.extend(node._values)
candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
return result
当方法_get_child_candidates
是否调用 ? 列表是否返回 ? 单元素 ? 是否又调用 ? 以后的呼叫何时停止 ?
1. 本代码由Jochen Schulz(jrschulz)编写,他为公制空间制作了一个伟大的Python图书馆。模块 m 空间.
虽然很多答案 表明你为什么会使用yield
要创建生成器, 有更多的用途yield
来传递两个代码区块之间的信息。我不会重复任何已经提供的关于使用yield
创建生成器。
帮助理解什么是yield
在以下代码中,您可以使用手指通过任何具有yield
。 每次你的手指碰到yield
你必须等待next
或 a/send
要输入。当next
被调用,你通过代码追踪 直到你击中yield
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .yield
被评价并返回到打电话者... 然后你等待。next
被再次调用,您通过代码执行另一个循环。 但是,你会注意到,在一条共同的常规中,yield
也可以与 a 一起使用send
... 将会从调用器中发送一个值与产生函数。如果send
给给, 然后给yield
接收发送的值,然后吐出左边的左手侧... 然后通过代码的追踪进展,直到你击中yield
再次返回(在结尾处返回值,如同next
也有人打电话))
例如:
>>> def coroutine():
... i = -1
... while True:
... i += 1
... val = (yield i)
... print("Received %s" % val)
...
>>> sequence = coroutine()
>>> sequence.next()
0
>>> sequence.next()
Received None
1
>>> sequence.send('hello')
Received hello
2
>>> sequence.close()
(我下面的回答只从使用Python发电机的角度,而不是从使用Python发电机的角度,而不是从使用Python发电机的角度来回答发电机机制基本实施,这涉及一些玩弄堆叠和堆积操纵的把戏。 ))
何时yield
使用代替return
在 python 函数中,该函数被转换为特殊的东西,称为generator function
该函数返回generator
类型。缩略yield
关键字是通知 Python 编译者专门处理此函数的标志。正常函数一旦从中返回某些值, 正常函数就会终止。 但是, 在编译器的帮助下, 生成器函数将会终止 。能够被想象到即,执行环境将恢复,执行将持续到最后一年。直到你明确要求返回,这会引起StopIteration
选项(这也是迭代协议的一部分),或达到函数的结尾。我发现很多关于generator
但这个1个调自自functional programming perspective
是最可消化的。
(现在我想谈一下为什么generator
和iterator
我希望这能帮助你掌握基本动机和基本动机这一概念以其他语言出现,如C#。 )
据我所知,当我们想要处理一堆数据时, 我们通常先把数据存放在某处,然后一个一个地处理。但是这个是。幼天如果数据量很大, 事先将数据全部储存起来是昂贵的 。而不是储存data
为什么不直接储存某种metadata
间接,即:the logic how the data is computed
.
有两种方法可以包扎这类元数据。
- OO 方法,我们包封元数据
as a class
这就是所谓的iterator
执行滚动协议(即__next__()
, 和__iter__()
这也是人们所普遍看到的方法。电动电机设计图案.
- 功能方法,我们包封元数据
as a function
这就是所谓的generator function
但是在兜帽帽下, 返回的人generator object
仍为IS-A
因为它还执行传动协议 。
无论哪种方式, 都会创建一个迭代器, 即某个可以提供您想要的数据的对象。 OO 处理方式可能有点复杂。 总之, 由您决定使用哪一种 。
这样想吧:
a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a. a.next()
方法。因此,一个产出式的函数最终会变成这样:
原文:
def some_function():
for i in xrange(4):
yield i
for i in some_function():
print i
Python 翻译用上述代码所做的基本上就是:
class it:
def __init__(self):
# Start at -1 so that we get 0 when we add 1 below.
self.count = -1
# The __iter__ method will be called once by the 'for' loop.
# The rest of the magic happens on the object returned by this method.
# In this case it is the object itself.
def __iter__(self):
return self
# The next method will be called repeatedly by the 'for' loop
# until it raises StopIteration.
def next(self):
self.count += 1
if self.count < 4:
return self.count
else:
# A StopIteration exception is raised
# to signal that the iterator is done.
# This is caught implicitly by the 'for' loop.
raise StopIteration
def some_func():
return it()
for i in some_func():
print i
更深入了解幕后发生的事for
循环可以重写到此 :
iterator = some_func()
try:
while 1:
print iterator.next()
except StopIteration:
pass
这更有意义还是更让人困惑?
我应当指出,这一点是a 为说明目的过于简化。 )
收益率与返回相似。区别是:
收益率使函数可适用(在下个示例中)primes(n = 1)
函数成为可使用性) 。
它的基本意思是 函数下次被调用时, 它将继续从它离开的地方( 位于yield expression
).
def isprime(n):
if n == 1:
return False
for x in range(2, n):
if n % x == 0:
return False
else:
return True
def primes(n = 1):
while(True):
if isprime(n): yield n
n += 1
for n in primes():
if n > 100: break
print(n)
在上述例子中,如果isprime(n)
这是真的, 它会返回质号。 在下次迭代中, 它会从下一行继续
n += 1