何为使用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 空间.
放弃是一个对象
A A Areturn
在函数中返回单一值。
如果您愿意,如果需要函数返回一大批值,使用yield
.
更重要的是yield
是 a 是障碍屏障.
就像CUDA语言中的屏障, 它不会转移控制 直到它完成。
也就是说,它会运行您函数的代码 从开始直到启动yield
。然后,它将返回循环的第一个值。
然后,其他每通电话都会运行您在函数中写下的循环, 返回下一个值, 直到没有任何值可以返回 。
收益率与返回相似。区别是:
收益率使函数可适用(在下个示例中)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
简单解答
函数至少包含一个时yield
语句,函数自动成为发电机功能。当您调用发电机功能时, python 在发电机功能中执行代码,直到yield
发生声明。yield
当您再次调用发电机功能时, python 继续从冻结位置执行发电机功能中的代码,直到yield
发电机函数执行代码直到发电机功能用完时没有yield
语句。
基准基准基准基准基准基准基准
创建列表并返回它 :
def my_range(n):
my_list = []
i = 0
while i < n:
my_list.append(i)
i += 1
return my_list
@profile
def function():
my_sum = 0
my_values = my_range(1000000)
for my_value in my_values:
my_sum += my_value
function()
结果有:
Total time: 1.07901 s
Timer unit: 1e-06 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
9 @profile
10 def function():
11 1 1.1 1.1 0.0 my_sum = 0
12 1 494875.0 494875.0 45.9 my_values = my_range(1000000)
13 1000001 262842.1 0.3 24.4 for my_value in my_values:
14 1000000 321289.8 0.3 29.8 my_sum += my_value
Line # Mem usage Increment Occurences Line Contents
============================================================
9 40.168 MiB 40.168 MiB 1 @profile
10 def function():
11 40.168 MiB 0.000 MiB 1 my_sum = 0
12 78.914 MiB 38.746 MiB 1 my_values = my_range(1000000)
13 78.941 MiB 0.012 MiB 1000001 for my_value in my_values:
14 78.941 MiB 0.016 MiB 1000000 my_sum += my_value
在飞行上生成值 :
def my_range(n):
i = 0
while i < n:
yield i
i += 1
@profile
def function():
my_sum = 0
for my_value in my_range(1000000):
my_sum += my_value
function()
结果有:
Total time: 1.24841 s
Timer unit: 1e-06 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
7 @profile
8 def function():
9 1 1.1 1.1 0.0 my_sum = 0
10
11 1000001 895617.3 0.9 71.7 for my_value in my_range(1000000):
12 1000000 352793.7 0.4 28.3 my_sum += my_value
Line # Mem usage Increment Occurences Line Contents
============================================================
7 40.168 MiB 40.168 MiB 1 @profile
8 def function():
9 40.168 MiB 0.000 MiB 1 my_sum = 0
10
11 40.203 MiB 0.016 MiB 1000001 for my_value in my_range(1000000):
12 40.203 MiB 0.020 MiB 1000000 my_sum += my_value
摘要摘要摘要
生成器函数需要稍多一点时间来执行, 而不是返回列表但少用内存的函数 。
python 的输出与返回语句类似,但有些差异除外。如果要从函数返回多个值,返回语句将把所有值都作为列表返回,并将其存储在调用符块的内存中。但如果我们不想使用额外的内存,会怎样?相反,我们需要在需要时从函数中获取该值。这是产出的来源。考虑以下函数:
def fun():
yield 1
yield 2
yield 3
打电话的人是:
def caller():
print ('First value printing')
print (fun())
print ('Second value printing')
print (fun())
print ('Third value printing')
print (fun())
上述代码段(调用函数),如果调用,产出:-
First value printing
1
Second value printing
2
Third value printing
3
从上文可以看出, 产出返回其调用器的值, 但当函数再次调用时, 它不会从第一个语句开始, 而是从产出后右侧的语句开始。 在上述示例中, “ 第一值打印” 打印, 函数被调用。 1 被回传并打印。 然后, 打印“ 第二值打印” , 并再次调用有趣 () 。 它不打印 1 (第一个语句) , 而是返回 2 , 也就是说, 仅从产出 1 之后的语句 。 同样的程序会进一步重复 。
又一个TRL;DR
列表中的迭代器: next()
返回列表的下一个元素
热机发电机: next()
将计算苍蝇上的下一个元素( 执行代码)
您可以看到生成/生成器作为手动运行控制流量从外部( 如继续循环一步骤) 调用next
无论流量如何复杂。
Note发电机是不无一个普通函数。它会像本地变量( stack) 一样记得以前的状态( stack) 。请参看其他答案或文章以详细解释。生成器只能是曾经变热过一次. 你可以没有yield
,但它不会是那么好, 所以它可以被认为是“非常好”的语言糖。
从方案拟订的角度来看,迭代器是按下列方式执行的: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
->