如何从__next__方法获得收益?

时间:2018-12-07 13:46:31

标签: python-3.x for-loop iterator generator yield

我认为以下代码可以表达所需的结果:

class LockIterator(object):

    def __init__(self, lock_list):
        self.lock_list = lock_list

    def __iter__(self):
        return self

    def __next__(self):

        for resource in self.lock_list:
            print( "Locking N resources" )

            yield resource
            print( "Unlocking N resources" )

        print( "Unlocking remaining resources" )
        raise StopIteration


for item in LockIterator( ["Resource 1", "Resource 2", "Resource 3"] ):
    print("Safe resource usage:", item)

但是,在Python上运行它,我得到了一个无限循环:

Safe resource usage: <generator object LockIterator.__next__ at 0x000001A8BDA24938>
Safe resource usage: <generator object LockIterator.__next__ at 0x000001A8BB8AEE60>
Safe resource usage: <generator object LockIterator.__next__ at 0x000001A8BDA24938>
Safe resource usage: <generator object LockIterator.__next__ at 0x000001A8BB8AEE60>
Safe resource usage: <generator object LockIterator.__next__ at 0x000001A8BDA24938>
Safe resource usage: <generator object LockIterator.__next__ at 0x000001A8BB8AEE60>
Safe resource usage: <generator object LockIterator.__next__ at 0x000001A8BDA24938>
Safe resource usage: <generator object LockIterator.__next__ at 0x000001A8BB8AEE60>
...

在我的想象中,它应该像这样运行:

Locking N resources
Safe resource usage: Resource 1
Unlocking N resources
Locking N resources
Safe resource usage: Resource 2
Unlocking N resources
Locking N resources
Safe resource usage: Resource 3
Unlocking N resources
Unlocking remaining resources

您知道如何在普通的for循环中自动强制这种行为吗?

for item in LockIterator( ["Resource 1", "Resource 2", "Resource 3"] ):
    print("Safe resource usage:", item)

2 个答案:

答案 0 :(得分:1)

每当for循环需要一个新项目时,就会调用

__next__。由于您的__next__是生成器,因此每次都会返回。

相反,您可以摆脱该类,而只需编写一个生成器:

def LockIterator(lock_list):
    # better name this lockify or something else in snake_case
    for resource in lock_list:
        print("Locking N resources")

        yield resource
        print("Unlocking N resources")

    print("Unlocking remaining resources")

答案 1 :(得分:1)

我还设法通过删除__next__并将其主体移至__iter__方法来对其进行修复:

class LockIterator(object):

    def __init__(self, lock_list):
        self.lock_list = lock_list

    def __iter__(self):

        for resource in self.lock_list:
            print( "Locking N resources" )

            yield resource
            print( "Unlocking N resources" )

        print( "Unlocking remaining resources" )

for item in LockIterator( ["Resource 1", "Resource 2", "Resource 3"] ):
    print("Safe resource usage:", item)