Bug or feature?

Robert Brewer fumanchu at amor.org
Thu Jan 15 01:05:46 EST 2004


Alexey Nezhdanov wrote:
> Hello. Found a strange python behaivoir while writing some 
> object. I've 
> stripped out all other stuff so the problem is stright here:
> =================================
> #!/usr/bin/python
> 
> class Object:
>      def __init__(self,val):
>          self.val=val
> 
>      def Sub(self,delta):
>          self.val-=delta
>          return delta
> 
> c=Object(1)
> 
> ### case 1 ###
> d=c.Sub(1)
> c.val+=d
> print 'case A:',c.val
> 
> ### case 2 ###
> c.val+=c.Sub(1)
> print 'case B:',c.val
> =================================
> Case 1 and case 2 prints out different calues (1 and 2 respectively).
> Do not know - if this is a bug or feature of python.

Disassembly is your friend:

>>> def pluseq(inst):
... 	inst.val += inst.Sub(1)
... 	
>>> dis.dis(pluseq)
  2           0 LOAD_FAST                0 (inst)
              3 DUP_TOP             
              4 LOAD_ATTR                1 (val)
              7 LOAD_FAST                0 (inst)
             10 LOAD_ATTR                2 (Sub)
             13 LOAD_CONST               1 (1)
             16 CALL_FUNCTION            1
             19 INPLACE_ADD         
             20 ROT_TWO             
             21 STORE_ATTR               1 (val)
             24 LOAD_CONST               0 (None)
             27 RETURN_VALUE        
>>> def subthenplus(inst):
... 	d = inst.Sub(1)
... 	inst.val += d
... 	
>>> dis.dis(subthenplus)
  2           0 LOAD_FAST                0 (inst)
              3 LOAD_ATTR                1 (Sub)
              6 LOAD_CONST               1 (1)
              9 CALL_FUNCTION            1
             12 STORE_FAST               1 (d)

  3          15 LOAD_FAST                0 (inst)
             18 DUP_TOP             
             19 LOAD_ATTR                3 (val)
             22 LOAD_FAST                1 (d)
             25 INPLACE_ADD         
             26 ROT_TWO             
             27 STORE_ATTR               3 (val)
             30 LOAD_CONST               0 (None)
             33 RETURN_VALUE        

As you can see, the order of evaluation in pluseq() is:
   load val, call Sub(), add, store result.
whereas the order in subthenplus() is:
   call Sub(), load val, add, store result.

...which explains things a bit. If we had written inst.val = inst.val +
inst.Sub(1), the order would be the same as pluseq (but we'd get a
binary add instead of inplace).


Robert Brewer
MIS
Amor Ministries
fumanchu at amor.org




More information about the Python-list mailing list