#๐Ÿ”’ generators and yield

83 messages ยท Page 1 of 1 (latest)

tropic steppeBOT
#

@timber mesa

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

surreal falcon
#

hey ๐Ÿ‘‹๐Ÿป

elfin cradle
#

generators are lazy

strange oak
#

next(gen) gives you the first item. each time you call next, you get the next item

elfin cradle
#

what it means that the values aren't calculated all at once

#

but when u need the value, it's being calculated

strange oak
#

to get the second item, you can either call next twice (the second call to next will be the second yielded item)
or you can use a utility like itertools.islice

half kindle
#

any reason for not returning a tuple? and iterating that?
is it only supposed to be iterated once?

surreal falcon
#

it is meant so it only produces as many values as you ask for

#

for example, there are infinite generators

#

and yeah it's one use

elfin cradle
#

i dont think u understand the concept much

#

or its usage

strange oak
#

generators are iterators

half kindle
#

yeah but you can only use em once then they exhaust?

elfin cradle
#

i think u need to first understand the iterator properties

strange oak
#

did we answer your original question or do you have a followup?

#

it seems as if we're going in circles or deviating from the actual question

elfin cradle
#

iterators main usage is to lazily iterate

#

calculate the values only when its needed

strange oak
#

this has been pointed out already

half kindle
#

you just use it when you don't wanna worry about indexes is all imo
call
next()
next()
next()
then do what ever you want and then starting iterating where you left
i.e 3

elfin cradle
#

item 6 is operation number 6 u can say

#

operation number 6 comes after operation number 5

strange oak
half kindle
strange oak
#

the function itself is technically the iterator object. the yields are the values that are returned via next

strange oak
elfin cradle
#

the function itself is a function

#

no

#

well either way

#

i think u're running too fast OP

hollow temple
#

The function is not an iterator. You call the function to get an iterator

strange oak
#

yeah that's my bad, just tested it

elfin cradle
#

good luck, i'm going back to python discusson

#

ping me if u need something

hollow temple
#

!e

def counter():
    n = 0
    while True:
        yield n
        n += 1
counter1 = counter()
counter2 = counter()
print(next(counter1), next(counter1), next(counter1))
print(next(counter2), next(counter2))
print(next(counter1), next(counter1))
tropic steppeBOT
strange oak
#

it seems like you think an iterator is an actual object that things subclass from, but it's just anything that implements both __next__ (i.e able to have next() called on it) and implements __iter__

half kindle
#

ye instead of destroying the stack frame it pauses it

#

for loop just keeps on calling next(gen)

#

until stopIteration

strange oak
hollow temple
#

In this case:

  • counter is called a "generator function"
  • counter1 is a "generator". A generator is a specific kind of iterator.
#

The point of a generator is to produce values lazily (meaning: on demand), instead of computing all of them and storing them in a list. When you call next(counter1) or do one iteration of a for loop over counter1, just enough code from the generator function is executed until it reaches yield <something>

#

yes

#

From a broader perspective, generator functions are a nice way of implementing iterators. You could implement the above with a class that has a manual __next__ implementation: ```py
class Counter:
def init(self):
self.n = 0

def __iter__(self):
    return self

def __next__(self):
    old_value = self.n
    self.n += 1
    return old_value
#

Yes

hollow temple
#

Another neat application of generator functions is contextlib.contextmanager (if you're familiar with context managers)

elfin cradle
#

there's a default implementation of iter?

hollow temple
#

my bad, fixed

elfin cradle
#

๐Ÿ‘ no worries

hollow temple
#

executing a yield doesn't create a new generator

#

You created a single generator by calling the counter function. The generator will yield integers

#

If a function contains the yield keyword, it's a "generator function" and not a normal one

#

Calling a generator function will just return a generator, yes

#

Calling the generator function returns a generator, which on its own will not do anything. The generator advances only when you call next() on it.

#

Look at the counter generator function for example. It has an infinite loop, so it's never going to stop producing values

#

If counter() waited until all the values were produced, it would never complete. That's the point of generators (or iterators in general): they produce the next item only when you ask for it

#

An iterator is a very generic thing. This is an iterator for example: #1418378203898318969 message
An iterator just needs to know how to generate a new item, it doesn't need a buffer or anything like that

#

When you call next(iterator), it just calls iterator.__next__()

#

For example, you could implement a list iterator like this: ```py
class ListIterator:
def init(self, items):
self.items = items
self.position = 0

def __iter__(self):
    return self

def __next__(self):
    if self.position >= len(self.items):
        self.items = []
        raise StopIteration  # no more items
    item = self.items[self.position]
    self.position += 1
    return item

numbers_iterated = ListIterator(numbers) # numbers_iterated is an iterator

#

(this is essentially what iter(a_list) does)

#

It runs until the code hits a yield. Then the value that's yielded becomes the result of the next() call.

#

so yes

#

A generator is just the name for the thing that's produced by a yield-containing function

#

From an outside perspective, it is just an iterator

#

something like that, yes

sour oriole
#

A generator is an iterator. Iterators just produce a potentially endless stream of values. Generators are iterators with extra capabilities.

hollow temple
#

It is a bit more complex, because you can also send a value to a generator with the .send() method (and throw an exception into it with .throw())

#

but if we ignore that, we just needed some word to call the result of a yield-function

#

and I guess the entire feature

#

If it contains yield, it's considered a generator function. That's the rule

#

For example, here's how you can make a generator function that yields no values: ```py
def v1():
if False:
yield 42

def v2():
return
yield 42

def v3():
for mystery in []:
yield 42

assert list(v1()) == []
assert list(v2()) == []
assert list(v3()) == []

#

so it's not dynamically decided, it's literally just whether one of the statements in the function is yield

#

It's not really a clone of the function, but it's an object that remembers all the local variables and where in the function it's currently executing

tropic steppeBOT
#
Python help channel closed using Discord native close action

This help channel has been closed. Feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.