Python 中的“return iter()”和“yield from”有什么区别?

What is the difference between `return iter()` and `yield from` in Python?

提问人:Huaijun Jiang 提问时间:11/16/2023 更新时间:11/18/2023 访问量:42

问:

和 in my case 之间有什么区别?还是我的代码正确?return iter()yield from

我希望我的类可以多次迭代。

请参阅下面的代码:

from typing import Iterable

class My_yield_from:
    def __init__(self):
        self.data = [1,2,3]
        self.tag = 'happy'

    def __iter__(self):
        yield from self.data

print('My_yield_from is Iterable?', isinstance(My_yield_from(), Iterable))

class My_iter:
    def __init__(self):
        self.data = [1,2,3]
        self.tag = 'happy'

    def __iter__(self):
        return iter(self.data)

print('My_iter is Iterable?', isinstance(My_iter(), Iterable))

测试代码:

my = My_yield_from()
print('first loop')
for i in my:
    print(i)

print('second loop')
for i in my:
    print(i)

print('another iter')
it = iter(my)
print(next(it))
print(next(it))
print(next(it))
try:
    print(next(it))
except StopIteration:
    print('StopIteration')

print('another iter')
it = iter(my)
print(next(it))
print(next(it))
print(next(it))
try:
    print(next(it))
except StopIteration:
    print('StopIteration')

print('two iters')
it1 = iter(my)
it2 = iter(my)
print(next(it1))
print(next(it2))
print(next(it1))
print(next(it2))
print(next(it1))
print(next(it2))
Python 迭代器 生成器

评论

2赞 matszwecja 11/16/2023
yield from允许您在它后面有其他语句。 将使以下任何内容都无法访问。return iter()

答:

2赞 SmellyCat 11/18/2023 #1

和之间的差值就像 和 之间的差值一样,在被调用时立即退出函数并返回给其调用者,但在控制返回给生成值的方法之前,将控制权传递给调用迭代函数或方法。returnyield fromreturnyieldreturnyieldyield from

我和这个演示一起扔了:

RANGE_TO_ITERATE = range(12)

def just_return_list():
    print("entering return_list")
    return iter(RANGE_TO_ITERATE)
    # Like Matszwecja points out, a print
    # statement here would be unreachable.

def generate_with_yield():
    for num in RANGE_TO_ITERATE:
        print(f"about to yield {num}..")
        yield num
        print(" ..yielded.")

def generate_with_yield_from():
   print("about to yield from..")
   yield from RANGE_TO_ITERATE
   print("\ndone yielding from")

return并且相似,因为您只调用它们一次。没有必要像 with 那样遍历单个元素。yield fromyield

如果我测试:return

print("Demonstrate return iter..")
for x in just_return_list():
   print(f"found {x}", end=", ")
print("\ndone demonstrating return iter")

它在写入任何元素之前进入和退出。just_return_list

Demonstrate return iter..
entering return_list
found 0, found 1, found 2, found 3, found 4, found 5, found 6, found 7, found 8, found 9, found 10, found 11, 
done demonstrating return iter

如果我测试:yield from

print("Demonstrate yield from..")
for x in generate_with_yield_from():
   print(f"found {x}",end=", ")
print("\ndone demonstrating yield from")

主要的可见区别是,我们可以看到进入和退出生成器函数的 print 语句。

Demonstrate yield from..
about to yield from..
found 0, found 1, found 2, found 3, found 4, found 5, found 6, found 7, found 8, found 9, found 10, found 11, 
done yielding from

done demonstrating yield from

随着我看到了更多的控制权转移:yield

print("Demonstrate yield..")
for x in generate_with_yield():
   print(f"found {x}",end=", ")
print("\ndone demonstrating yield")
Demonstrate yield..
about to yield 0..
found 0,  ..yielded.
about to yield 1..
found 1,  ..yielded.
about to yield 2..
found 2,  ..yielded.
about to yield 3..
found 3,  ..yielded.
about to yield 4..
found 4,  ..yielded.
about to yield 5..
found 5,  ..yielded.
about to yield 6..
found 6,  ..yielded.
about to yield 7..
found 7,  ..yielded.
about to yield 8..
found 8,  ..yielded.
about to yield 9..
found 9,  ..yielded.
about to yield 10..
found 10,  ..yielded.
about to yield 11..
found 11,  ..yielded.

done demonstrating yield

评论

0赞 Huaijun Jiang 11/23/2023
因此,如果我只想实现并使MyClass_object可多次迭代,是否可以并被视为技术上等效?for x in MyClass_object: do()return iter()yield from