Python Forum
generator function that yield from a list
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
generator function that yield from a list
#1
Let's say we have a string lie this 'a b c' (simplified example)
so we can do
spam = 'a b c'
for ch in spam.split(' '):
    print(ch)


in this case str.split() will produce a list (i.e. it will generate the whole list in memory)

for same result we can do also

def chars(eggs):
   for ch in eggs.split(' '):
       yield ch

spam = 'a b c'
for ch in chars(spam):
    print(ch)
in this case the generator function chars will not produce the list from eggs.split() in memory, right? it will be evaluated lazy? I started to doubt myself today answering on SO question... Blush
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#2
This is not answer, but in corner case (if you don't mind spaces / there are no spaces) one can yield directly:

>>> def chars(word):
...     yield from word
...
>>> for char in chars('abc'):
...     print(char)
...
a
b
c
>>> for char in chars('a b c'):
...     if char != ' ':
...         print(char)
a
b
c
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#3
As I said this was simplified example. Here is link to my answer on SO. Note also my comment under it.

If it was simply str, I would iterate directly over it (i.e. it's in the memory anyway, generally no benefit to create a generator)
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#4
I think re.finditer() will work for this.
>>> import re
>>> 
>>> spam = 'a b c'
>>> for match in re.finditer(r'\S+', spam):
...     print(match.group())
...     
a
b
c
re.finditer() is an True iterator,and will not store values in memory.
Should work for more complicated cases as can write regex pattern for a lot stuff.
So next() and __next__ before values get used.
>>> r = re.finditer(r'a', 'a')
>>> r
<callable_iterator object at 0x04C5FFB0>
>>> next(r)
<re.Match object; span=(0, 1), match='a'>


>>> r = re.finditer(r'a', 'a')
>>> r.__next__()
<re.Match object; span=(0, 1), match='a'>
Reply
#5
@snippsat, thanks, but my question is more or less theoretical (please check also the SO)
basically, I ask I ask if we have (pseudocode)
def spam():
    for egg in <SOME LIST/TUPLE OBJECT HERE, e.g. returned by some function or method like str.split()>:
       yield egg
does python evaluate the list/tuple when creating the generator function I.e. create the whole list in memory or it is evaluated lazy only when yield next value. I think it's the later
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#6
Only the yield will be lazy the str.split() will return a full list.
Reply
#7
(Jun-04-2019, 08:57 PM)Yoriz Wrote: Only the yield will be lazy the str.split() will return a full list.
so, if that is the case, it doesn't make sense to create the generator function in this particular case
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#8
This would be lazy, no extra list created.
def chars(eggs):
    for ch in eggs:
        if ch != " ":
            yield ch


spam = "a b c"
for ch in chars(spam):
    print(ch)
Output:
a b c
Reply
#9
this was my actual case/answer on SO:

def get_addresses(input_string):
    for address in input_string.split(' BEG ')[-1].split(' END ')[0].split(' '):
        yield address

foo = "70D76320 BEG 701D135D 702D72FC END EAR0 00000000 0000000"
for idx, address in enumerate(get_addresses(foo)):
    print(f'[{idx}]0x{address}')
they wanted alternative to using regex to extract address values between BEG and END and format them in a particular way.

and the user asked if there is performance benefit in using generator function compared to directly iterate over foo.split(' BEG ')[-1].split(' END ')[0].split(' '). My comment was that
Quote:in this particular case (assuming you will not have many addresses) there is no practical difference. In general case split() will produce list in memory, while get_addresses is generator and it will not produce the whole list in the memory. In addition it makes the code more structured and allows to test the generator function separately.
Then I had second thoughts and asked here... I should have posted the actual code from the start...
:-) Anyway, thanks a lot
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#10
Here with re.finditer(),so it's still regex but an alternative way of using regex.
addresses = btInfo.group().split()
for idx in range(len(addresses)):
So here use @r0ng split() and range(len(addresses),together with regex.

import re

foo = "70D76320 BEG 701D135D 702D72FC END EAR0 00000000 0000000"
for match in re.finditer(r'BEG\s(.*?)\s(.*?)\s', foo):
    for idx,address in enumerate(iter(match.groups())):
        print(f'[{idx}]0x{address}')
Output:
[0]0x701D135D [1]0x702D72FC
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  yield from akbarza 4 146 11 hours ago
Last Post: DeaD_EyE
  yield usage as statement or expression akbarza 5 796 Oct-23-2023, 11:43 AM
Last Post: Gribouillis
  Using list comprehension with 'yield' in function tester_V 5 1,247 Apr-02-2023, 06:31 PM
Last Post: tester_V
  Tuple generator, and function/class syntax quazirfan 3 3,866 Aug-10-2021, 09:32 AM
Last Post: buran
  What is the difference between a generator and a list comprehension? Pedroski55 2 2,213 Jan-02-2021, 04:24 AM
Last Post: Pedroski55
  Yield generator weird output Vidar567 8 3,274 Nov-23-2020, 10:59 PM
Last Post: deanhystad
  Creating list of lists from generator object t4keheart 1 2,202 Nov-13-2020, 04:59 AM
Last Post: perfringo
  list call problem in generator function using iteration and recursive calls postta 1 1,902 Oct-24-2020, 09:33 PM
Last Post: bowlofred
  Trying to access next element using Generator(yield) in a Class omm 2 1,967 Oct-19-2020, 03:36 PM
Last Post: omm
  Yield statement question DPaul 6 2,512 Sep-26-2020, 05:18 PM
Last Post: DPaul

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020