Building up on @Madlozoz answer, but with mighty walrus operator:
>>> gen = (x ** 2 for x in itertools.count())
>>> [v := next(gen) for _ in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> v
81
The thing I don't like about this (unlike Madlozoz') solution is that potentially huge list is constructed just to be discarded immediately.
A simple for loop is another way:
# `gen` continues from the previous snippet
>>> for _ in range(3):
... v = next(gen)
...
>>> print(v)
144
At a cost of extra line we can save some process ticks on assignments as well and spend them on wrapper class:
class IterIndexer:
def __init__(self, iter_):
self.iter = iter_
def __getitem__(self, i):
for _ in range(i - 1):
next(self.iter)
return next(self.iter)
gen = (x ** 2 for x in itertools.count())
gen = IterIndexer(gen)
print(gen[14])
169
It'd be even cooler to wrap it properly, so that you can use wrapper instance for everything instead of original generator or iterator, but that's another question =)