[Python-ideas] Possible PEP 380 tweak (original) (raw)
Carl M. Johnson cmjohnson.mailinglist at gmail.com
Fri Oct 29 05:17:14 CEST 2010
- Previous message: [Python-ideas] Possible PEP 380 tweak
- Next message: [Python-ideas] Possible PEP 380 tweak
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On Thu, Oct 28, 2010 at 4:21 PM, Guido van Rossum <guido at python.org> wrote:
On Thu, Oct 28, 2010 at 6:17 PM, Nick Coghlan <ncoghlan at gmail.com> wrote:
To use a toy example:
# Even this toy framework needs a little structure class EndSum(Exception): pass def gsum(): # Sums sent values until EndSum or GeneratorExit are thrown in tally = 0 try: while 1: tally += yield except (EndSum, GeneratorExit): pass return x You meant return tally. Right? def averagesums(): # Advances to a new sum when EndSum is thrown in # Finishes the last sum and averages them all when GeneratorExit is thrown in sums = [] try: while 1: sums.append(yield from gsum()) except GeneratorExit as ex: # Our proposed expansion tweak is to enable the next line sums.append(ex.args[0]) return sum(sums) / len(sums)
This toy example is a little confusing to me because it has typos… which is natural when one is writing a program without being able to run it to debug it. So, I wrote a version of the accumulator/averager that will work in Python 2.7 (and I think 3, but I didn't test it):
class ReturnValue(Exception): pass
def prime_pump(gen): def f(*args, **kwargs): g = gen(*args, **kwargs) next(g) return g return f
@prime_pump def accumulator(): total = 0 length = 0 try: while 1: value = yield total += value length += 1 print(length, value, total) except GeneratorExit: r = ReturnValue() r.total = total r.length = length raise r
@contextmanager def get_sum(it): try: it.close() except ReturnValue as r: yield r.total
@contextmanager def get_average(it): try: it.close() except ReturnValue as r: yield r.total / r.length
def main(): running_total = accumulator() sums = accumulator() running_total.send(6) #For example, whatever running_total.send(7) with get_sum(running_total) as first_sum: sums.send(first_sum)
running_total = accumulator() #Zero it out
running_total.send(2) #For example, whatever
running_total.send(2)
running_total.send(5)
running_total.send(8)
with get_sum(running_total) as second_sum:
sums.send(second_sum)
#Get the average of the sums
with get_average(sums) as r:
return r
main()
So, I guess the question I have is how will the proposed extensions to the language make the above code prettier? One thing I can see is that if it's possible to return from inside a generator, it can be more straightforward to get the values out of the accumulator at the end:
try:
while 1:
value = yield
total += value
length += 1
print(length, value, total)
except GeneratorExit:
return total, length
With Guido's proposed "for item from yield" syntax, IIUC this can be prettied up even more as:
for value from yield:
total += value
length += 1
return total, length
Are there other benefits to the proposed extensions? How will the call sites be improved? I'm not sure how I would rewrite main() to be prettier/more clear in light of the proposals…
Thanks,
-- Carl Johnson
- Previous message: [Python-ideas] Possible PEP 380 tweak
- Next message: [Python-ideas] Possible PEP 380 tweak
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]