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
这更有意义还是更让人困惑?
我要指出,为了说明起见,这过于简单化。 )
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 之后的语句 。 同样的程序会进一步重复 。
和每个答案一样, 收益被用于创建序列生成器。 它用于动态生成某些序列。 例如, 在按行阅读网络文件行时, 您可以使用以下的收益函数 :
def getNextLines():
while con.isOpen():
yield con.read()
您可在您的代码中使用以下代码:
for line in getNextLines():
doSomeThing(line)
执行控制控制
执行控制将会从 GetNextLines () 转到执行时的循环。 因此, 每次引用 NextLines () 时, 执行都会从上次暂停处开始 。
因此,简言之,一个函数具有以下代码
def simpleYield():
yield "first time"
yield "second time"
yield "third time"
yield "Now some useful value {}".format(12)
for i in simpleYield():
print i
将打印
"first time"
"second time"
"third time"
"Now some useful value 12"
也可以将数据发送回生成器!
事实上,正如这里许多答案所解释的那样,利用产量产生一个发电机。
您可以使用产出关键字将数据发送回“实时”生成器。
示例:
假设我们有一种方法可以从英语翻译成其他语言。 在开始的时候, 它会做一些很重的事情, 应该做一次。 我们希望这个方法可以永远运行( 不知道为什么..... . :) , 并且收到要翻译的单词 。
def translator():
# load all the words in English language and the translation to 'other lang'
my_words_dict = {'hello': 'hello in other language', 'dog': 'dog in other language'}
while True:
word = (yield)
yield my_words_dict.get(word, 'Unknown word...')
运行中 :
my_words_translator = translator()
next(my_words_translator)
print(my_words_translator.send('dog'))
next(my_words_translator)
print(my_words_translator.send('cat'))
将打印 :
dog in other language
Unknown word...
概括如下:
使用发件人内部发送方法将数据发送回发件人。要允许,使用 a (ield) 。
生成关键字用于查点/字符,其中函数预期将返回一个输出。我想引用这个非常简单的例A:
# example A
def getNumber():
for r in range(1,10):
return r
以上函数只返回一次, 即使它被多次调用。 现在如果我们以收益率替换返回, 如例B :
# example B
def getNumber():
for r in range(1,10):
yield r
当第一次叫2时,它会返回1,当再次叫2时,3,4,然后它会递增到10。
虽然B的例子在概念上是真实的,但要用Python 3来称呼它,我们必须采取以下行动:
g = getNumber() #instance
print(next(g)) #will print 1
print(next(g)) #will print 2
print(next(g)) #will print 3
# so to assign it to a variables
v = getNumber()
v1 = next(v) #v1 will have 1
v2 = next(v) #v2 will have 2
v3 = next(v) #v3 will have 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)