Reputation: 9428
I thought the following code would express the desired result:
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)
But, running it on Python I got an infinity loop:
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>
...
In my imagination, it was supposed to run like this:
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
Do you know how could automatically force this behavior in a ordinary for loop?
for item in LockIterator( ["Resource 1", "Resource 2", "Resource 3"] ):
print("Safe resource usage:", item)
Upvotes: 1
Views: 541
Reputation: 9428
I also manage to fix it by deleting the __next__
and moving its body to the __iter__
method:
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)
Upvotes: 3
Reputation: 27283
__next__
is called every time the for loop needs a new item. Since your __next__
is a generator, that is what is returned every time.
Instead, you could get rid of the class and just write a generator:
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")
Upvotes: 2