何为使用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 空间.
通常情况下, 它会用来创建一个不起作用的代名词。 将“ ield” 当作您函数的附加件, 以及您作为数组的函数。 如果符合某些标准, 您可以在函数中添加此值, 使之成为代名词 。
arr=[]
if 2>0:
arr.append(2)
def func():
if 2>0:
yield 2
两者的输出结果相同。
使用产量的主要优势是创建迭代器。 迭代器在即时计算时不会计算每个项目的价值。 它们只在您要求时才计算。 这被称为懒惰评价 。
TL; DR TR; TL; TDR
代替此:
def square_list(n):
the_list = [] # Replace
for x in range(n):
y = x * x
the_list.append(y) # these
return the_list # lines
这样做:
def square_yield(n):
for x in range(n):
y = x * x
yield y # with this one.
每当你发现自己从头到尾 编造了一张清单yield
换成每块
这是我第一次"啊哈"节奏节奏
yield
是 a 是糖糖说
构建一系列材料
相同行为 :
>>> for square in square_list(4):
... print(square)
...
0
1
4
9
>>> for square in square_yield(4):
... print(square)
...
0
1
4
9
不同的行为 :
成绩是单行:只有一次循环才能通过。当一个函数在其中产生产量时,我们把它称为发电机功能和一个振动器也就是它所返回的。这些术语是明亮的。我们失去了一个容器的方便,但获得了一系列的能量, 而这些能量是按需要计算, 并且任意地长。
成绩是懒惰,它会推迟计算计算。当你叫它时,它不会实际执行。返回函数返回振动器对象记得它留下的痕迹 每次你打电话next()
转动器上(这发生在换行)行刑的几英寸向下一产地前进。return
提高停止电流并结束序列( 这是循环的自然端 ) 。
成绩是多功能性。数据不必全部储存在一起,数据可以一次提供一次。数据可以是无限的。
>>> def squares_all_of_them():
... x = 0
... while True:
... yield x * x
... x += 1
...
>>> squares = squares_all_of_them()
>>> for _ in range(4):
... print(next(squares))
...
0
1
4
9
需要时多个通行证系列剧不会太长,只是打个电话list()
以下列方式:
>>> list(square_yield(4))
[0, 1, 4, 9]
最聪明的词选yield
原因原因双两个意思应用 :
收益率生产或供应(如农业)
...在系列中提供下一个数据
收益率- 放弃或放弃(与政治权力一样)
...在传动器推进之前,将CPU执行。
下面是浅白语言的例子。我将提供高层次人类概念与低层次Python概念之间的对应关系。
我想用数字序列操作, 但我不想用这个序列的创建来烦恼我自己, 我只想专注于我想做的操作。 因此, 我做以下工作:
- 我打电话给你,告诉你,我想要一个数字序列 以特定的方式计算, 我让你知道算法是什么。
此步骤对应于def
内插入发电机函数,即包含yield
.
- 稍后,我告诉你, "好了,准备好告诉我数字的顺序"。
此步骤对应于调用发电机函数, 以返回发电机对象 。注意不要告诉我任何数字 你只要拿起你的纸和铅笔
- 我问你,"告诉我下一个号码",然后你告诉我第一个号码, 在那之后,你等我问你下一个号码。你的工作是记住你在哪里,你已经说过什么号码,下一个号码是什么。 我不在乎细节。
此步骤对应于调用next(generator)
在发电机的物体上。
(在Python 2,.next
是产生器物体的一种方法;在Python 3中,它被命名为.__next__
,但正确的称呼方式是使用内置next()
函数类似len()
和.__len__
)
- ...重复前一步,直到...
- 最终,你可能会走到尽头。你不会告诉我一个数字;你只会喊叫,“抓住你的马!我受够了!不再有数字了!”
此步骤对应于生成器对象结束工作, 并提升StopIteration
例外。
生成器函数不需要提出例外。 当函数结束或发布时自动生成 。return
.
这就是发电机(包含yield
;它开始执行第一个next()
时暂停yield
,当要求next()
它从最后一点继续值 。 它的设计完全符合 Python 的迭代协议, 它描述了如何按顺序请求值 。
循环程序最著名的用户是for
在 Python 中命令。 所以, 当您做 :
for item in sequence:
这不重要,如果sequence
是列表、字符串、字典或生成器对象对象如上文所述;结果相同:您逐个阅读顺序中的项目。
请注意def
函数内含有yield
关键字不是创建生成器的唯一方法; 它只是创建生成器的最简单的方法 。
将 " 更准确的信息 " 改为 " 更准确的信息 "迭代器类型、、 和收益单报表和发电机发电机在 Python 文档中。
从方案拟订的角度来看,迭代器是按下列方式执行的:Tunks 缩图.
实施迭代机、发电机和用于同时执行的线性集合,等等,作为杜丘,一种用途发送到关闭对象的信件它有一个调度员, 和给“ 消息” 的发件人解答.
"下一个"是发送到结束处的电文,该电文由“创建者”创建。亚列"打电话。
执行此计算有很多方法。 我使用突变, 但可以通过返回当前值和下一个生成者( 生成者) 返回当前值和下一个生成者( 生成者) 来进行这种不突变的计算( 生成者)优惠透明Racket使用一些中间语言对初始方案进行一系列转换,其中之一是进行这种改写,使产量经营者与较简单的经营者以某种语言进行转换。
这是如何重写产量的演示, 它使用 R6RS 的结构, 但语义与 Python 的相同 。 这是相同的计算模式, 只需要修改语法, 才能使用 Python 的 产量重写 。
Welcome to Racket v6.5.0.3.
-> (define gen
(lambda (l)
(define yield
(lambda ()
(if (null? l)
'END
(let ((v (car l)))
(set! l (cdr l))
v))))
(lambda(m)
(case m
('yield (yield))
('init (lambda (data)
(set! l data)
'OK))))))
-> (define stream (gen '(1 2 3)))
-> (stream 'yield)
1
-> (stream 'yield)
2
-> (stream 'yield)
3
-> (stream 'yield)
'END
-> ((stream 'init) '(a b))
'OK
-> (stream 'yield)
'a
-> (stream 'yield)
'b
-> (stream 'yield)
'END
-> (stream 'yield)
'END
->
收益率与返回相似。区别是:
收益率使函数可适用(在下个示例中)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
又一个TRL;DR
列表中的迭代器: next()
返回列表的下一个元素
热机发电机: next()
将计算苍蝇上的下一个元素( 执行代码)
您可以看到生成/生成器作为手动运行控制流量从外部( 如继续循环一步骤) 调用next
无论流量如何复杂。
Note发电机是不无一个普通函数。它会像本地变量( stack) 一样记得以前的状态( stack) 。请参看其他答案或文章以详细解释。生成器只能是曾经变热过一次. 你可以没有yield
,但它不会是那么好, 所以它可以被认为是“非常好”的语言糖。