[Python-Dev] Splitting something into two steps produces different behavior from doing it in one fell swoop in Python 2.6.2

MRAB python at mrabarnett.plus.com
Fri Dec 11 20:43:35 CET 2009


John Arbash Meinel wrote:
> Roy Hyunjin Han wrote:
>> While debugging a network algorithm in Python 2.6.2, I encountered
>> some strange behavior and was wondering whether it has to do with some
>> sort of code optimization that Python does behind the scenes.
>>
>>
>> ************
>> After initialization: defaultdict(<type 'set'>, {1: set([1])})
>> Popping and updating in two steps: defaultdict(<type 'set'>, {1: set([1])})
>> ************
>> After initialization: defaultdict(<type 'set'>, {1: set([1])})
>> Popping and updating in one step: defaultdict(<type 'set'>, {})
>>
>>
>> import collections
>> print '************'
>> x = collections.defaultdict(set)
>> x[1].update([1])
>> print 'After initialization: %s' % x
>> items = x.pop(1)
>> x[1].update(items)
>> print 'Popping and updating in two steps: %s' % x
>> print '************'
>> y = collections.defaultdict(set)
>> y[1].update([1])
>> print 'After initialization: %s' % y
>> y[1].update(y.pop(1))
>> print 'Popping and updating in one step: %s' % y
>>
> 
> y[1].update(y.pop(1))
> 
> is going to be evaluating y[1] before it evaluates y.pop(1).
> Which means that it has the original set returned, which is then removed
> by y.pop, and updated.
> 
> You probably get the same behavior without using a defaultdict:
>   y.setdefault(1, set()).update(y.pop(1))
>   ^^^^^^^^^^^^^^^^^^^^^^- evaluated first
> 
> 
> Oh and I should probably give the standard: "This list is for the
> development *of* python, not development *with* python."
> 
To me the question was whether Python was behaving correctly; the
behaviour was more subtle than the legendary mutable default argument.


More information about the Python-Dev mailing list