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