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链接。
这样想吧:
迭代器只是具有下一个( ) 方法的对象的奇特探测术语。 因此, 产生式的函数最终会变成这样 :
原文:
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
为了更深入地了解幕后发生的事情,
iterator = some_func()
try:
while 1:
print iterator.next()
except StopIteration:
pass
这更有意义还是更让人困惑?
我要指出,为了说明起见,这过于简单化。 )
所有的答案都是伟大的, 但对于新人来说有点困难。
我猜你已经得知回程声明了
作为类比,回归和收益是双胞胎。 回归意味着“ 回归和停止 ” , 而“ 回归”则意味着“回归,但继续 ” 。
尝试获得一份有回报的 num_ 列表 。
def num_list(n):
for i in range(n):
return i
运行它:
In [5]: num_list(3)
Out[5]: 0
你看,你只得到一个数字,而不是一个他们的名单。返回永远不允许你快乐地获胜,只要执行一次就退出。
产生结果
将返回替换为产出 :
In [10]: def num_list(n):
...: for i in range(n):
...: yield i
...:
In [11]: num_list(3)
Out[11]: <generator object num_list at 0x10327c990>
In [12]: list(num_list(3))
Out[12]: [0, 1, 2]
现在,你赢得了所有的数字。
与一次运行和停止的返回相比, 一次运行和一次运行, 一次运行和一次运行。 您可以将返回解释为一个返回, 一次返回作为全部返回。 这叫“ 易动 ” 。
再多走一步,我们就可以重新写出回报的收益声明
In [15]: def num_list(n):
...: result = []
...: for i in range(n):
...: result.append(i)
...: return result
In [16]: num_list(3)
Out[16]: [0, 1, 2]
这是关于产量的核心。
列表返回输出与目标产出的区别是:
您总是可以从列表对象中获取 [0, 1, 2] , 但只能从“ 对象输出输出” 中提取一次 。 因此, 它有一个新的名称生成对象, 如 Out[ 11] 所示 : <generator 对象 num_ list at 0x10327c990> 。
最后,作为格罗克语的比喻:
双胞胎名单和发电机是双胞胎
以下是一些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)
又一个TRL;DR
列表中的迭代器 : 下一个 () 返回列表的下一个元素 。
迭代生成器: 下一个 () 将计算苍蝇上的下一个元素( 执行代码)
您可以通过下拨“无论流量如何复杂”,将产出/生成器视为手动运行外部控制流的一种方式(如继续循环一步),然后调用该输出/生成器作为手动运行外部控制流的一种方式。
注意 : 生成器不是一个正常的函数。 它会像本地变量( stack) 一样记住先前的状态 。 请参看其他答案或文章以详细解释 。 生成器只能重复一次 。 您可以不生产, 但不会是那么好, 所以它可以被视为“ 非常好” 的语言糖 。