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_camedates 被调用时会怎样? 列表是否返回? 单一个元素吗? 是否再次调用? 以后的电话何时停止?
1. 本代码由Jochen Schulz(jrschulz)编写,他为公制空间制作了一个伟大的Python图书馆,与完整的源:模块mspace链接。
发电机可以使个别经过处理的物品立即得到处理(不必等待整个收集过程的处理),下面的例子说明了这一点。
import time
def get_gen():
for i in range(10):
yield i
time.sleep(1)
def get_list():
ret = []
for i in range(10):
ret.append(i)
time.sleep(1)
return ret
start_time = time.time()
print('get_gen iteration (individual results come immediately)')
for i in get_gen():
print(f'result arrived after: {time.time() - start_time:.0f} seconds')
print()
start_time = time.time()
print('get_list iteration (results come all at once)')
for i in get_list():
print(f'result arrived after: {time.time() - start_time:.0f} seconds')
get_gen iteration (individual results come immediately)
result arrived after: 0 seconds
result arrived after: 1 seconds
result arrived after: 2 seconds
result arrived after: 3 seconds
result arrived after: 4 seconds
result arrived after: 5 seconds
result arrived after: 6 seconds
result arrived after: 7 seconds
result arrived after: 8 seconds
result arrived after: 9 seconds
get_list iteration (results come all at once)
result arrived after: 10 seconds
result arrived after: 10 seconds
result arrived after: 10 seconds
result arrived after: 10 seconds
result arrived after: 10 seconds
result arrived after: 10 seconds
result arrived after: 10 seconds
result arrived after: 10 seconds
result arrived after: 10 seconds
result arrived after: 10 seconds
- 功能 - 返回。
发电机 -- -- 产量(含有一个或多个产量和零或更多回报率)。
names = ['Sam', 'Sarah', 'Thomas', 'James']
# Using function
def greet(name) :
return f'Hi, my name is {name}.'
for each_name in names:
print(greet(each_name))
# Output:
>>>Hi, my name is Sam.
>>>Hi, my name is Sarah.
>>>Hi, my name is Thomas.
>>>Hi, my name is James.
# using generator
def greetings(names) :
for each_name in names:
yield f'Hi, my name is {each_name}.'
for greet_name in greetings(names):
print (greet_name)
# Output:
>>>Hi, my name is Sam.
>>>Hi, my name is Sarah.
>>>Hi, my name is Thomas.
>>>Hi, my name is James.
发电机看起来像一个函数,但行为举止却像一个迭代器。
发件人继续从它所在的位置执行 。 恢复后, 函数在最后产值运行后立即继续执行 。 这允许它的代码在一段时间内生成一系列的值, 代之以它们一次性计算全部值, 然后把它们像列表一样送回去 。
def function():
yield 1 # return this first
yield 2 # start continue from here (yield don't execute above code once executed)
yield 3 # give this at last (yield don't execute above code once executed)
for processed_data in function():
print(processed_data)
#Output:
>>>1
>>>2
>>>3
注:放弃不应在尝试中.最终建造。
以下是一些Python的例子, 说明如何实际安装发电机, 仿佛Python没有提供同声糖:
作为Python发电机:
from itertools import islice
def fib_gen():
a, b = 1, 1
while True:
yield a
a, b = b, a + b
assert [1, 1, 2, 3, 5] == list(islice(fib_gen(), 5))
使用地法关闭代替发电机
def ftake(fnext, last):
return [fnext() for _ in xrange(last)]
def fib_gen2():
#funky scope due to python2.x workaround
#for python 3.x use nonlocal
def _():
_.a, _.b = _.b, _.a + _.b
return _.a
_.a, _.b = 0, 1
return _
assert [1,1,2,3,5] == ftake(fib_gen2(), 5)
使用关闭物体而不是发电机(因为关闭物体和物体是等效的)
class fib_gen3:
def __init__(self):
self.a, self.b = 1, 1
def __call__(self):
r = self.a
self.a, self.b = self.b, self.a + self.b
return r
assert [1,1,2,3,5] == ftake(fib_gen3(), 5)
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.
每当你发现自己从头开始编出一个清单时, 每一块都取而代之。
这是我第一次"啊哈"节奏节奏
收成是一种含糖的方式 说
构建一系列材料
相同行为 :
>>> for square in square_list(4):
... print(square)
...
0
1
4
9
>>> for square in square_yield(4):
... print(square)
...
0
1
4
9
不同的行为 :
产量是单行道,只能绕过一次。当一个函数有收益时,我们称它为发电机功能。循环者就是它的回报。这些术语是明亮的。我们失去了一个容器的方便,但获得一系列按需要计算并任意延长的能量。
是懒惰的, 它会推卸计算。 函数中含有收益的函数在调用时不会实际执行。 它返回一个循环器对象, 记得它留下的位置。 每次您在调用循环器时( 这发生在换环) 执行步数向下一个产数前进。 返回会提高停止输出并结束序列( 这是换圈的自然结束 ) 。
产量是多功能的。数据不必全部储存在一起, 它可以一次提供一次。 它可以是无限的 。
>>> 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(square_yield(4))
[0, 1, 4, 9]
英明地选择“产生”一词,因为这两个含义都适用:
产量——生产或供应(如农业)
...在系列中提供下一个数据
放弃或放弃(与政治权力一样)
...在传动器推进之前,将CPU执行。
许多人使用回报而不是生产,但在某些情况下,收益可以更有效和更便于工作。
这里的例子绝对是收成最佳的:
返回( 在函数)
import random
def return_dates():
dates = [] # With 'return' you need to create a list then return it
for i in range(5):
date = random.choice(["1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th"])
dates.append(date)
return dates
产出(在函数)
def yield_dates():
for i in range(5):
date = random.choice(["1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th"])
yield date # 'yield' makes a generator automatically which works
# in a similar way. This is much more efficient.
呼叫功能
dates_list = return_dates()
print(dates_list)
for i in dates_list:
print(i)
dates_generator = yield_dates()
print(dates_generator)
for i in dates_generator:
print(i)
两种函数都做同样的事情, 但产量使用三行而不是五行, 并且有一个更少的变量要担心。
这是代码的结果:
调
您可以看到两个函数都做相同的事情。 唯一的区别是 返回_ dates () 给出了列表, 而 收益_ dates () 给出了生成器 。
真实生活中的范例就是 逐行读取文件行 或者你只是想制造一个发电机
简单使用实例 :
>>> def foo():
yield 100
yield 20
yield 3
>>> for i in foo(): print(i)
100
20
3
>>>
如何运行 : 调用时, 函数会立即返回对象。 对象可以传递到下一个( ) 函数 。 当调用下一个( ) 函数时, 您的函数会一直运行到下一个产值, 并为下一个( ) 函数提供返回值 。
在引擎盖下, 循环确认对象是一个生成对象, 并使用下一个( ) 来获取下一个值 。
在一些语言中,比如ES6和更高语言中,它的实施略有不同, 所以下一个是生成对象的成员函数, 每次它得到下一个值时, 你就可以从调用器中传递数值。 所以如果结果是生成器, 那么你可以做类似y=结果。 ext( 555) , 而程序生成值可以说像 z = 产值 999 。 y 的值将是 999 , 下一个产值是 999, 而 z 的值将是 555 , 下一个产值是 555。 Python 获取并发送方法也有类似的效果 。