C
Carlos Ribeiro
As a side track of my latest investigations, I began to rely heavily
on generators for some stuff where I would previsouly use a more
conventional approach. Whenever I need to process a list, I'm tending
towards the use of generators. One good example is if I want to print
a report, or to work over a list with complex processing for each
item. In both cases, a simple list comprehension can't be used. The
conventional approach involves setting up a empty result list, looping
over the list while appending the result, and finally returning it.
For strings, it's something like this:
def myfunc(items):
result = []
result += ["Start of processing"]
for item in items:
# do some processing with item
...
result += [str(item)]
result += ["End of processing"]
return result
This code is not only ugly to read, but it's inefficient because of
the way list and string concatenations are handled. Other alternatives
involve adding directly to the string, or using CStringIO. But I think
you've got the point. Now, using generators, the function code gets
simpler:
def myfunc(items):
yield "Start of processing"
for item in items:
# do some processing with item
...
yield str(item)
yield "End of processing"
I can print the results either way:
a) for line in myfunc([...]): print line
b) print "\n".list(myfunc([...]))
And I have other advantages -- no concatenations in the function code,
and the list can be generated as needed. This has the potential to
make the system less resource intensive (specially for large lists)
and more responsive.
Now, just because I can do it does not mean it's a good idea For
particular cases, a measurement can be done. But I'm curious about the
generic case. What is the performance penalty of using generators in
situations as the ones shown above?
--
Carlos Ribeiro
Consultoria em Projetos
blog: http://rascunhosrotos.blogspot.com
blog: http://pythonnotes.blogspot.com
mail: (e-mail address removed)
mail: (e-mail address removed)
on generators for some stuff where I would previsouly use a more
conventional approach. Whenever I need to process a list, I'm tending
towards the use of generators. One good example is if I want to print
a report, or to work over a list with complex processing for each
item. In both cases, a simple list comprehension can't be used. The
conventional approach involves setting up a empty result list, looping
over the list while appending the result, and finally returning it.
For strings, it's something like this:
def myfunc(items):
result = []
result += ["Start of processing"]
for item in items:
# do some processing with item
...
result += [str(item)]
result += ["End of processing"]
return result
This code is not only ugly to read, but it's inefficient because of
the way list and string concatenations are handled. Other alternatives
involve adding directly to the string, or using CStringIO. But I think
you've got the point. Now, using generators, the function code gets
simpler:
def myfunc(items):
yield "Start of processing"
for item in items:
# do some processing with item
...
yield str(item)
yield "End of processing"
I can print the results either way:
a) for line in myfunc([...]): print line
b) print "\n".list(myfunc([...]))
And I have other advantages -- no concatenations in the function code,
and the list can be generated as needed. This has the potential to
make the system less resource intensive (specially for large lists)
and more responsive.
Now, just because I can do it does not mean it's a good idea For
particular cases, a measurement can be done. But I'm curious about the
generic case. What is the performance penalty of using generators in
situations as the ones shown above?
--
Carlos Ribeiro
Consultoria em Projetos
blog: http://rascunhosrotos.blogspot.com
blog: http://pythonnotes.blogspot.com
mail: (e-mail address removed)
mail: (e-mail address removed)