On Jun 20, 2019, at 13:25, nate lust <firstname.lastname@example.org> wrote:
There is nothing more humbling than sending nonsense out to an entire mailing list.
You’re something like the 300th person to suggest overloading assignment, but the only one of that 300 willing to think it through, much less create a patch. That’s hardly something to feel bad about!
There are other supporting changes, but the core idea is just that the type struct (typeobject.c) now has one more field (I called it tp_setself) that under normal circumstances is just 0. Then in the insertdict function (dictobject.c) (which does just what it sounds), post looking up the old value, and pre setting anything new, I added a block to check if tp_setself is defined on the type of the old value. If it is this means the user defined a __setself__ method on a type and it is called with the value that was to be assigned causing whatever side effects the user chose for that function, and the rest of insertdict body is never run.
Intercepting this at the namespace’s dict rather than at the store op is a really clever idea, and it seems like it should avoid the major performance hit as well. But I have a few questions.
Does assigning a local variable actually call dictinsert anywhere? There is a locals dict, but I believe it’s only created and kept up to date with the fast locals array if you ask for it.
What about other namespaces that aren’t dicts, like attributes of __slots__ classes?
What about dicts that aren’t namespaces? For example, will x[y] = z call __setself__ on x[y] if x is a dict, but not if it’s a list (and if it’s a SortedDict it may or may not depending on internal details of how that’s implemented under the covers)?
Will x += y call __setself__(self) after the __iadd__(y)?
I’m not entirely sure what the right answer is for all of these situations. And that might depend on how you describe this protocol in the docs (the name “setself” doesn’t necessarily imply the same thing as “overloading assignment”).