itertools.takewhile
is the correct way to express what you're asking, but it depends on a module which necessarily adds a line.
>>> import itertools
>>> print(list(itertools.takewhile(lambda x: x < 1000, (3**x for x in itertools.count()))))
[1, 3, 9, 27, 81, 243, 729]
Expressed in a more sane 3-liner format...
>>> import itertools
>>> for x in itertools.takewhile(lambda x: x < 1000, (3**x for x in itertools.count())):
... print(x)
...
1
3
9
27
81
243
729
Let's explain what's going on here, starting from the innermost. Each step builds on the previous.
itertools.count()
is a generator that produces the numbers 1, 2, 3, 4, ...
forever. It's how you express range(infinity)
.
(3**x for x in itertools.count())
is a generator that produces the numbers 1, 3, 9, 27, ...
forever.
itertools.takewhile(lambda x: x < 1000, (3**x for x in itertools.count()))
is a generator that produces the numbers 1, 3, 9, 27, ...
forever while x < 1000
is true.
After that it's just a matter of printing the generated numbers.
The itertools module is a pretty important part of Python, I suggest learning it in general as it solves a lot of problems like this.