Suggesting a new feature - "Inverse Generators"
Peter Otten
__peter__ at web.de
Sat Mar 26 03:04:57 EST 2005
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
More information about the Python-list
mailing list