[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