Python 什么是;“收益率”;你要做什么?
在Python中,Python 什么是;“收益率”;你要做什么?,python,iterator,generator,yield,coroutine,Python,Iterator,Generator,Yield,Coroutine,在Python中,yield关键字有什么用途?它有什么作用 例如,我试图理解以下代码1: >>> mygenerator = (x*x for x in range(3)) >>> for i in mygenerator: ... print(i) 0 1 4 def\u获取子对象(自我、距离、最小距离、最大距离): 如果self.\u leftchild和距离-最大距离=self.\u中间值: 屈服于自己 这是来电者: result, candi
yield
关键字有什么用途?它有什么作用
例如,我试图理解以下代码1:
>>> mygenerator = (x*x for x in range(3))
>>> for i in mygenerator:
... print(i)
0
1
4
def\u获取子对象(自我、距离、最小距离、最大距离):
如果self.\u leftchild和距离-最大距离=self.\u中间值:
屈服于自己
这是来电者:
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
result,候选者=[],[self]
而候选人:
node=candidates.pop()
距离=节点。获取距离(obj)
如果距离=最小距离:
结果.扩展(节点。\u值)
扩展(节点获取子候选对象(距离、最小距离、最大距离))
返回结果
调用方法\u get\u child\u candidates
时会发生什么?
是否返回列表?单一元素?又叫了吗?后续通话何时停止
1.这段代码是由Jochen Schulz(jrschulz)编写的,他为度量空间创建了一个很棒的Python库。这是指向完整源代码:[Module mspace][1]的链接。
yield
就像return
-它返回您告诉它的任何内容(作为生成器)。不同之处在于,下次调用生成器时,执行从上次调用yield
语句开始。与return不同,当发生屈服时,堆栈帧不会被清除,但是控制权会被转移回调用方,因此下次调用函数时,其状态将恢复。
对于您的代码,函数get_child_candidates
的作用类似于迭代器,因此当您扩展列表时,它会一次向新列表添加一个元素
list.extend
调用迭代器,直到迭代器耗尽。对于您发布的代码示例,只返回一个元组并将其附加到列表中会更清楚。yield
就像return
——它返回您告诉它的任何内容(作为生成器)。不同之处在于,下次调用生成器时,执行从上次调用yield
语句开始。与return不同,当发生屈服时,堆栈帧不会被清除,但是控制权会被转移回调用方,因此下次调用函数时,其状态将恢复。
对于您的代码,函数get_child_candidates
的作用类似于迭代器,因此当您扩展列表时,它会一次向新列表添加一个元素
list.extend
调用迭代器,直到迭代器耗尽。对于您发布的代码示例,只返回一个元组并将其附加到列表中会更清楚。它返回一个生成器。我对Python不是特别熟悉,但我相信这与您熟悉Python是一样的
关键思想是编译器/解释器/任何东西都会做一些诡计,以便对调用方而言,它们可以继续调用next(),并且它将继续返回值,就像生成器方法被暂停一样。现在很明显,你不能真正“暂停”一个方法,所以编译器会为你建立一个状态机,让你记住你现在在哪里,以及局部变量是什么样子。这比自己编写迭代器容易得多。它返回一个生成器。我对Python不是特别熟悉,但我相信这与您熟悉Python是一样的 关键思想是编译器/解释器/任何东西都会做一些诡计,以便对调用方而言,它们可以继续调用next(),并且它将继续返回值,就像生成器方法被暂停一样。现在很明显,你不能真正“暂停”一个方法,所以编译器会为你建立一个状态机,让你记住你现在在哪里,以及局部变量是什么样子。这比自己编写迭代器要容易得多。这样想: 迭代器只是具有
next()
方法的对象的一个听起来很奇特的术语。所以一个屈服函数最终是这样的:
def fib():
last, cur = 0, 1
while True:
yield cur
last, cur = cur, last + cur
for f in fib():
if some_condition: break
coolfuncs(f);
>>> isinstance(gen, types.GeneratorType)
True
>>> isinstance(gen, collections.Iterator)
True
原文:
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
这更有意义还是让你更困惑
我应该注意到,出于说明的目的,这是一种过于简单的说法。:) 这样想:
迭代器只是具有next()
方法的对象的一个听起来很奇特的术语。所以一个屈服函数最终是这样的:
def fib():
last, cur = 0, 1
while True:
yield cur
last, cur = cur, last + cur
for f in fib():
if some_condition: break
coolfuncs(f);
>>> isinstance(gen, types.GeneratorType)
True
>>> isinstance(gen, collections.Iterator)
True
原文:
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
这更有意义还是让你更困惑
我应该注意到,出于说明的目的,这是一种过于简单的说法。:) 要理解
yield
的功能,您必须了解生成器是什么。在你能理解发电机之前,你必须先理解易逝性
易怒
创建列表时,可以逐个读取其项。逐项读取其项目称为迭代:
>>> mylist = [1, 2, 3]
>>> for i in mylist:
... print(i)
1
2
3
mylist
是一个iterable。当您使用列表理解时,您会创建一个列表,从而创建一个iterable:
>>> mylist = [x*x for x in range(3)]
>>> for i in mylist:
... print(i)
0
1
4
>>> list(makeRange(5))
[0, 1, 2, 3, 4]
您可以在上使用“for…in…
”的所有内容都是可编辑的<代码>列表,字符串
,文件
这些iterables非常方便,因为您可以随意读取它们,但是您可以将所有值存储在内存中,当您有很多值时,这并不总是您想要的
发电机
生成器是迭代器,一种iterable,您只能迭代一次。生成器不会将所有值存储在内存中,而是动态生成值:
>>> mygenerator = (x*x for x in range(3))
>>> for i in mygenerator:
... print(i)
0
1
4
除了您使用了()
而不是[]
之外,它是一样的。但是,您不能在mygenerator中为i执行
for f in fib():
if some_condition: break
coolfuncs(f);
for x in mylist:
...loop body...
def f123():
yield 1
yield 2
yield 3
for item in f123():
print item
generator = myYieldingFunction(...)
x = list(generator)
generator
v
[x[0], ..., ???]
generator
v
[x[0], x[1], ..., ???]
generator
v
[x[0], x[1], x[2], ..., ???]
StopIteration exception
[x[0], x[1], x[2]] done
list==[x[0], x[1], x[2]]
def makeRange(n):
# return 0,1,2,...,n-1
i = 0
while i < n:
yield i
i += 1
>>> makeRange(5)
<generator object makeRange at 0x19e4aa0>
>>> list(makeRange(5))
[0, 1, 2, 3, 4]
# list-version # # generator-version
def makeRange(n): # def makeRange(n):
"""return [0,1,2,...,n-1]""" #~ """return 0,1,2,...,n-1"""
TO_RETURN = [] #>
i = 0 # i = 0
while i < n: # while i < n:
TO_RETURN += [i] #~ yield i
i += 1 # i += 1 ## indented
return TO_RETURN #>
>>> makeRange(5)
[0, 1, 2, 3, 4]
# _ITERABLE_
>>> [x+10 for x in makeRange(5)]
[10, 11, 12, 13, 14]
>>> x=iter(range(5))
>>> next(x)
0
>>> next(x)
1
>>> next(x)
2
>>> next(x)
3
>>> next(x)
4
>>> next(x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
> x = myRange(5)
> list(x)
[0, 1, 2, 3, 4]
> list(x)
[]
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)
def get_odd_numbers(i):
return range(1, i, 2)
def yield_odd_numbers(i):
for x in range(1, i, 2):
yield x
foo = get_odd_numbers(10)
bar = yield_odd_numbers(10)
foo
[1, 3, 5, 7, 9]
bar
<generator object yield_odd_numbers at 0x1029c6f50>
bar.next()
1
bar.next()
3
bar.next()
5
>>> def f():
... yield 1
... yield 2
... yield 3
...
>>> g = f()
>>> for i in g:
... print(i)
...
1
2
3
>>> for i in g:
... print(i)
...
>>> # Note that this time nothing was printed
def save_file(filename):
def write_file_continuation():
write_stuff_to_file(filename)
check_if_file_exists_and_user_wants_to_overwrite(write_file_continuation)
def f():
while True:
yield 4
class Generator():
def __init__(self,iterable,generatorfun):
self.next_continuation = lambda:generatorfun(iterable)
def next(self):
value, next_continuation = self.next_continuation()
self.next_continuation = next_continuation
return value
def generatorfun(iterable):
if len(iterable) == 0:
raise StopIteration
else:
return (iterable[0], lambda:generatorfun(iterable[1:]))
def normalFunction():
return
if False:
pass
def yielderFunction():
return
if False:
yield 12
>>> yielderFunction()
<generator object yielderFunction at 0x07742D28>
>>> gen = yielderFunction()
>>> dir(gen)
['__class__',
...
'__iter__', #Returns gen itself, to make it work uniformly with containers
... #when given to a for loop. (Containers return an iterator instead.)
'close',
'gi_code',
'gi_frame',
'gi_running',
'next', #The method that runs the function's body.
'send',
'throw']
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
->
def isPrimeNumber(n):
print "isPrimeNumber({}) call".format(n)
if n==1:
return False
for x in range(2,n):
if n % x == 0:
return False
return True
def primes (n=1):
while(True):
print "loop step ---------------- {}".format(n)
if isPrimeNumber(n): yield n
n += 1
for n in primes():
if n> 10:break
print "wiriting result {}".format(n)
loop step ---------------- 1
isPrimeNumber(1) call
loop step ---------------- 2
isPrimeNumber(2) call
loop step ---------------- 3
isPrimeNumber(3) call
wiriting result 3
loop step ---------------- 4
isPrimeNumber(4) call
loop step ---------------- 5
isPrimeNumber(5) call
wiriting result 5
loop step ---------------- 6
isPrimeNumber(6) call
loop step ---------------- 7
isPrimeNumber(7) call
wiriting result 7
loop step ---------------- 8
isPrimeNumber(8) call
loop step ---------------- 9
isPrimeNumber(9) call
loop step ---------------- 10
isPrimeNumber(10) call
loop step ---------------- 11
isPrimeNumber(11) call
>>> def coroutine():
... i = -1
... while True:
... i += 1
... val = (yield i)
... print("Received %s" % val)
...
>>> sequence = coroutine()
>>> sequence.next()
0
>>> sequence.next()
Received None
1
>>> sequence.send('hello')
Received hello
2
>>> sequence.close()
yield from <expr>
async def new_coroutine(data):
...
await blocking_action()
>>> def func():
... yield 'I am'
... yield 'a generator!'
...
>>> type(func) # A function with yield is still a function
<type 'function'>
>>> gen = func()
>>> type(gen) # but it returns a generator
<type 'generator'>
>>> hasattr(gen, '__iter__') # that's an iterable
True
>>> hasattr(gen, 'next') # and with .next (.__next__ in Python 3)
True # implements the iterator protocol.
>>> import collections, types
>>> issubclass(types.GeneratorType, collections.Iterator)
True
>>> isinstance(gen, types.GeneratorType)
True
>>> isinstance(gen, collections.Iterator)
True
>>> list(gen)
['I am', 'a generator!']
>>> list(gen)
[]
>>> list(func())
['I am', 'a generator!']
def func(an_iterable):
for item in an_iterable:
yield item
def func(an_iterable):
yield from an_iterable
def bank_account(deposited, interest_rate):
while True:
calculated_interest = interest_rate * deposited
received = yield calculated_interest
if received:
deposited += received
>>> my_account = bank_account(1000, .05)
>>> first_year_interest = next(my_account)
>>> first_year_interest
50.0
>>> next_year_interest = my_account.send(first_year_interest + 1000)
>>> next_year_interest
102.5
expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) |
('=' (yield_expr|testlist_star_expr))*)
...
yield_expr: 'yield' [yield_arg]
yield_arg: 'from' test | testlist
def getNextLines():
while con.isOpen():
yield con.read()
for line in getNextLines():
doSomeThing(line)
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 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]
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)
def simple_generator():
yield 'one'
yield 'two'
yield 'three'
for i in simple_generator():
print i
one
two
three
def myRangeNaive(i):
n = 0
range = []
while n < i:
range.append(n)
n = n + 1
return range
for i in myRangeNaive(10):
print i
def myRangeSmart(i):
n = 0
while n < i:
yield n
n = n + 1
return
for i in myRangeSmart(10):
print i
def f123():
for _ in range(4):
yield 1
yield 2
for i in f123():
print (i)
1 2 1 2 1 2 1 2
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]