0

I want to use a list comprehension to call this function.

def perfect_squares(limit):
    value = 1
    while value < limit:
        yield value*value
        value += 1

foo = perfect_squares(1000)
for i in range(6):
    print(next(foo))
wrkyle
  • 529
  • 1
  • 13
  • 36
  • 1
    This is not grammatical Python. Please make sure your code is a [example]. Notably, your indentation is wrong, and will generate an error. – Amadan Nov 21 '19 at 01:38
  • @taseikyo I reverted your edit because I'm pretty sure the function's not supposed to be recursive, but let's let OP fix it. – wjandrea Nov 21 '19 at 03:55
  • @wrkyle Writing a function is not the same as calling a function. Please don't make edits that change the meaning of a post. You could edit your edit to remove that change. – wjandrea Nov 21 '19 at 03:58
  • @Amadan is right, please fix your code. If it helps, check out [Formatting help - code](/editing-help#code) – wjandrea Nov 21 '19 at 04:00

2 Answers2

3

I believe you’re looking for a comprehension so the function still is a generator

def perfect_squares(limit):
    yield from (v*v for v in range(1,limit))

Or as returning a actual list using a list comprehension:

def perfect_squares(limit):
    return [v*v for v in range(1,limit)]
Jab
  • 26,853
  • 21
  • 75
  • 114
  • 1
    Is there advantage to `yield from genexpr` vs `return genexpr` in this context? (Serious question, I'm still new to `yield from`) – Amadan Nov 21 '19 at 01:46
  • `yield from` is the same contextually as `for x in y: yield z` So yes the function would still be a generator vs being a regular function returning a generator. – Jab Nov 21 '19 at 01:47
  • I understand that; it's just that invoking either will still result in a generator object. `list(yield_from_fn())` is exactly the same as `list(loop_yield_fn())`. (Also, `yield from` is [not quite the same](https://stackoverflow.com/a/26109157/240443) as a yielding loop, though it's a good enough explanation in this context.) Never mind, I'm overthinking this. :P – Amadan Nov 21 '19 at 01:51
  • @Amadan In this simple context, not really. But `yield from ... ` doesn't, you know, *return* from the function. You can write `def single_digits_twice(): yield from range(10); yield from range(10)`, which is considerably different from `def single_digits_twice(): return range(10); return range(10)` (which only yields the single-digit numbers once). – chepner Nov 21 '19 at 01:55
  • 1
    Note: the `yield from` expression was introduced in python 3.3 and is detailed in [PEP 380](https://www.python.org/dev/peps/pep-0380/) it was added for a purpose as the return object from yielding is `` and returning a genexp is `. at 0x116dd13b8>`. So both perform the same while they do differ. In the end it’s down to how you plan to use it and/or code style. – Jab Nov 21 '19 at 02:05
2

Since you are using yield, you cannnot do this with list comprehension. If you want to use list comprehension, you should produce the whole list first, and then print them instead.

Without yield, you can do it as follows:

power_of_2 = [x ** 2 for x in range(1, 1000)] 
Vishal
  • 3,178
  • 2
  • 34
  • 47
  • This is incorrect. List comprehension without square brackets creates a generator just like a function with `yield` does. These are equivalent: `def squares(): for i in range(5): yield i*i` and `(i * i for i in range(5))`. (Granted, it's called a "generator expression" and not really "list comprehension" then.) – Amadan Nov 21 '19 at 01:39
  • Thanks for the clarification Amadan. Yes, I have answered w.r.t. the actual question which said "list comprehension". – Vishal Nov 21 '19 at 01:47