-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
C/Python difference: Setting __class__ activates in C, doesn't activate in Python #155
Comments
Probably closely related: The C implementation sets $ python /tmp/t.py
Setting the class
Setting state in A
Object is changed? True
...
$ PURE_PYTHON=1 python /tmp/t.py
Setting the class
Object is changed? None
... This is another reason why I prefer the Python behaviour. But I assume there's reasons the C code does what it does (I haven't checked). |
There don't really seem to be any reasons that the C code does what it does; it could be changed to match Python, but that's a non-starter for backwards compatibility. I also discovered this same discrepancy applies to It also applies to a few other special attributes: |
…like C. By activating the object. Add tests for this. In the process of adding tests, I discovered the mock pickle cache used by the Python tests was returning the wrong thing from new_ghost (not a ghost), so I fixed this and added some extra tests and assertions to be sure the behaviour matches with the real and C caches. Fixes #155
The C behaviour makes sense to me if you view an object's class as part of its state (and there are some design patterns in Python that (ab)use OTOH, I seem to remember that the way persistent references work is that each object that has a reference to some persistent object stores a tuple of (class name, oid), which makes me question whether it's even a good idea to allow changing |
True. I did exactly that (state machine based on
… and this is why it doesn't work on ZODB: ZODB stores the That said, changing the class can still be useful at runtime if you're very careful. |
In the C implementation, setting
__class__
of a ghost calls_p_activate()
, and uses the class methods defined on the original class.But in the Python implementation, setting
__class__
does not call_p_activate()
; consequently, the class methods of the new class are used.This makes a difference when class methods include those used in the pickle protocol, such as
__setstate__
.Here's an example. Consider this code:
When we run it with the C implementation, the object is activated by the line
a.__class__ = B
and uses theA.__setstate__
implementation to do so.Using the pure-Python version, however, activation doesn't happen until we call
_p_activate()
explicitly, and then it uses theOther.__setstate__
implementation.Ideally, setting the class of a ghost wouldn't activate the object, I think. But since that's the way the C implementation has worked for some time, probably the Python implementation needs to change to activate the object when the class is assigned to.
The text was updated successfully, but these errors were encountered: