[ZODB-Dev] Re: false write conflicts

John Belmonte john at neggie.net
Tue Mar 2 12:10:51 EST 2004


Casey Duncan wrote:
> John Belmonte <john at neggie.net> wrote:
> 
>>Casey Duncan wrote:
>>
>>>Augmented assignment causes a setattr on the containing object. This
>>>is the way Python works. These examples are semantically
>>>equivilant::
>>>
>>>  self.x += 1
>>>  self.x = self.x + 1
>>>  setattr(self, 'x', self.x + 1)
>>>
>>>They all cause self to be modified through __setattr__. If self is a
>>>persistent instance then it will be marked changed in all three
>>>cases above.
>>
>>To be more accurate, it seems like
>>
>>    foo.bar += 1
>>
>>becomes the equivalent of
>>
>>    x = foo.bar; x += 1; foo.bar = x
> 
> Ok, I'm not sure how that's more accurate ;^) My example don't create a
> local variable 'x'.

The reason I said that was because your equivalents didn't show the += 
operator being called on the attribute object.  What I'm trying to show 
is that Python doesn't blow off calling the object's += method just 
because it's accessed as an attribute of some other object.

>>That is arguably a Python wart.  With regard to the containing object,
>>
>>it seems unfortunate to consider "foo.bar +=1" different than 
>>"foo.bar[a] = b".
> 
> It's not a wart. Augmented assignment is an assignment operation. If it
> is an assignent to an attribute, that changes the containing object. A
> positive side-affect of this wrt persistence is that augmented assigment
> of mutable non-persistent attributes actually does the "right thing".
> i.e.::
> 
> Where:
>   self.x = []
> 
>   self.x += 'foo'
> 
> marks self as changed which actually "helps" you since
> self.x.append('foo') wouldn't.

I guess my view is different than Python's, but the augmented assignment 
is an assignment to the object contained in the attribute, not to the 
container (that is, the containing class).  It doesn't change the 
containing object unless the augmented operation yields a new object 
(and my setattr wrapper handles this case fine).

 From your example, I consider "self.x += 'foo'" triggering a database 
write, while "self.x.append('foo')" does not, to be inconsistent and 
useless.  list.__iadd__ and list.append have the same meaning.


>>This wrapper for Persistent.__setattr__ looks like it will suit my
>>needs:
>>
>>   class MyPersistent(Persistent):
>>     def __setattr__(self, key, val):
>>       if not (self.__dict__.has_key(key) and self.__dict__[key] is
>>       val):
>>         Persistent.__setattr__(self, key, val)
> 
> Ugh. This is bound to bite you somewhere down the line. I'd say its
> simpler to avoid augmented assignment when you don't want the container
> marked as changed. But that's me.

I don't think it will bite me because it makes the behavior of 
persistent objects match the model in my head:  if I don't assign a new 
object or value to an attribute, don't flag the containing object as dirty.

-John


-- 
http:// if  ile.org/



More information about the ZODB-Dev mailing list