Как выйти из метода __next__? - PullRequest
       68

Как выйти из метода __next__?

0 голосов
/ 07 декабря 2018

Я думал, что следующий код даст желаемый результат:

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 голосов
/ 08 декабря 2018

Мне также удается исправить это, удалив __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)
0 голосов
/ 07 декабря 2018

__next__ вызывается каждый раз, когда циклу for требуется новый элемент.Поскольку ваш __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")
...