Current value of generator
Question:
In Python I can build a generator like so:
def gen():
x = range(0, 100)
for i in x:
yield i
I can now define an instance of the generator using:
a = gen()
And pull new values from the generator using
a.next()
But is there a way—a.current()
—to get the current value of the generator?
Answers:
You set the value of a variable.
current_value = a.next()
then use current_value for all it’s worth.
Python uses this often in for statements
a = xrange(10)
for x in a:
print(x)
Here you are defining x as the current value of a.
There isn’t such a method, and you cannot add attributes to a generator. A workaround would be to create an iterator object that wraps your generator, and contains a ‘current’ attribute. Taking it an extra step is to use it as a decorator on the generator.
Here’s a utility decorator class which does that:
class with_current(object):
def __init__(self, generator):
self.__gen = generator()
def __iter__(self):
return self
def __next__(self):
self.current = next(self.__gen)
return self.current
def __call__(self):
return self
You can then use it like this:
@with_current
def gen():
x=range(0,100)
for i in x:
yield i
a = gen()
print(next(a))
print(next(a))
print(a.current)
Outputs:
0
1
1
Using another global variable to store the current value might be feasible.
# Variable that store the current value of the generator
generator_current_val = None
def generator():
global generator_current_val # to set the current value
for i in range(10):
generator_current_val = i
yield i
a = generator()
print(next(a)) # 0
print(next(a)) # 1
print(next(a)) # 2
print(generator_current_val) # 2
print(next(a)) # 3
You can use a sliding window generator, something like
def _window(i: Iterator[T]) -> Iterator[Tuple[T, Optional[T]]]:
prev = None
for x in i:
if prev:
yield prev, x
prev = x
yield prev, None
i = _window(iter([1,2,3,4]))
print(next(i)) # (1, 2)
print(next(i)) # (2, 3)
print(next(i)) # (3, 4)
print(next(i)) # (4, None)
In Python I can build a generator like so:
def gen():
x = range(0, 100)
for i in x:
yield i
I can now define an instance of the generator using:
a = gen()
And pull new values from the generator using
a.next()
But is there a way—a.current()
—to get the current value of the generator?
You set the value of a variable.
current_value = a.next()
then use current_value for all it’s worth.
Python uses this often in for statements
a = xrange(10)
for x in a:
print(x)
Here you are defining x as the current value of a.
There isn’t such a method, and you cannot add attributes to a generator. A workaround would be to create an iterator object that wraps your generator, and contains a ‘current’ attribute. Taking it an extra step is to use it as a decorator on the generator.
Here’s a utility decorator class which does that:
class with_current(object):
def __init__(self, generator):
self.__gen = generator()
def __iter__(self):
return self
def __next__(self):
self.current = next(self.__gen)
return self.current
def __call__(self):
return self
You can then use it like this:
@with_current
def gen():
x=range(0,100)
for i in x:
yield i
a = gen()
print(next(a))
print(next(a))
print(a.current)
Outputs:
0
1
1
Using another global variable to store the current value might be feasible.
# Variable that store the current value of the generator
generator_current_val = None
def generator():
global generator_current_val # to set the current value
for i in range(10):
generator_current_val = i
yield i
a = generator()
print(next(a)) # 0
print(next(a)) # 1
print(next(a)) # 2
print(generator_current_val) # 2
print(next(a)) # 3
You can use a sliding window generator, something like
def _window(i: Iterator[T]) -> Iterator[Tuple[T, Optional[T]]]:
prev = None
for x in i:
if prev:
yield prev, x
prev = x
yield prev, None
i = _window(iter([1,2,3,4]))
print(next(i)) # (1, 2)
print(next(i)) # (2, 3)
print(next(i)) # (3, 4)
print(next(i)) # (4, None)