| Store | Cart

Suggesting a new feature - "Inverse Generators"

From: Peter Otten <__pe...@web.de>
Sat, 26 Mar 2005 09:04:57 +0100
Jordan Rastrick wrote:

>> No, it's nothing special about groupby.  record simply stores its> state in a>> mutable default parameter.  This isn't general good practice: at> least you have>> to be careful with it.  You can see the behavior in the following> example:>>   >>> def accumulate(value, accum = []):>>   ...     accum.append(value)>>   ...     return accum>>   ...>>   >>> accumulate(1)>>   [1]>>   >>> accumulate(2)>>   [1, 2]>>   >>> accumulate(6)>>   [1, 2, 6]>>   >>>> > Wow.... I'd never seen this kind of thing in examples of Python code.> Although its really neat, it doesn't really make sense, intuituvely to> me. Why does accum remember its state - I suppose its to do with the> scope of arguments (as opposed to method variables) or something like> that?

Michael's accumulator uses the fact that default arguments are only
evaluated once -- when the function is created. The behaviour shown above
is actually a common trap every newbie has to experience once until he
learns the workaround:

def accumulate(value, a=None):
    if a is None:
        a = []
    a.append(value)
    return a

> Still, thats powerful. But I see why its not standard use -  it could> be easily abused!

There are limitations, too. If you want more than one accumulator you have
to pass the accum argument explicitly or wrap accumulate() into a factory:

def make_accumulator():
    def accumulate(value, a=[]):
        a.append(value)
        return a
    return accumulate

Sill, you cannot get hold of the result of the accumulation without
modifying it. One way to fix that:

>>> def make_accumulator():
...     a = []
...     def accumulate(value):
...             a.append(value)
...     return a, accumulate
...
>>> items1, accu1 = make_accumulator()>>> for i in range(4): accu1(i)
...
>>> items1
[0, 1, 2, 3]
>>> items2, accu2 = make_accumulator()>>> for i in "abc": accu2(i)
...
>>> items2
['a', 'b', 'c']
>>> items1
[0, 1, 2, 3]

Now this is all nice and dandy to play around with and learn something about
Python's scoping rules, but you can get the same functionality in a
straightforward way with a callable object (like Bengt Richter's Grouper)
and that is what I would recommend.

Peter

Recent Messages in this Thread
Jordan Rastrick Mar 25, 2005 04:04 pm
Jordan Rastrick Mar 25, 2005 04:10 pm
Andrew Koenig Mar 25, 2005 04:18 pm
Jordan Rastrick Mar 25, 2005 04:36 pm
Andrew Koenig Mar 26, 2005 01:40 pm
Tim Hochberg Mar 25, 2005 04:25 pm
Michael Spencer Mar 25, 2005 04:46 pm
Jordan Rastrick Mar 25, 2005 05:23 pm
Michael Spencer Mar 25, 2005 06:41 pm
Serge Orlov Mar 25, 2005 07:14 pm
Jordan Rastrick Mar 26, 2005 06:56 am
Peter Otten Mar 26, 2005 08:04 am
Scott David Daniels Mar 25, 2005 07:34 pm
Michael Spencer Mar 25, 2005 08:07 pm
Scott David Daniels Mar 25, 2005 09:00 pm
Bengt Richter Mar 25, 2005 10:11 pm
Bengt Richter Mar 25, 2005 07:43 pm
Terry Reedy Mar 25, 2005 07:13 pm
Jordan Rastrick Mar 25, 2005 04:49 pm
Diez B. Roggisch Mar 25, 2005 06:13 pm
Jordan Rastrick Mar 26, 2005 04:11 pm
phil...@yahoo.com Mar 27, 2005 03:44 am
Oren Tirosh Mar 27, 2005 06:58 am
Messages in this thread