There seems to be some confusion to what is going on with the __getself__ method. This is almost certainly dues to my lack of communicating things clearly. I am going to attempt to walk through what will happen in context of a code example. The important thing to keep in mind is that __getself__ is invoked only on named object access, i.e. LOAD_VALUE, and not on variables accessed from a container, or fetched from the stack (in the case of the cpython interpreter access. Say we have the following "expression template" from my examples.py. I will be using the types SimpleArray, and SimpleArrayExecutor, where the later has __getself__ defined. a, b, and c are instances of SimpleArray.
d = a + b + c print(d)
now for a similar case
tmp = a + b d = tmp + c print(d)
This results in the same result, but with an extra loop. This can be avoided by using the built in getcloaked (the function name is up in the air) similar to the object.__getattr__ escape hatch. I.E.:
tmp = a + b d = getcloaked(tmp) + c prtint(d)
Now the behavior is the same as the first case, as getcloaked returns the metavariable that has not been bound to a name and so it is loaded right on the stack.
There are two (three) important cases when I have exempt __getself__ from being called. First is when an object is used in methods defined within itself. This means that self can be used when defining methods without triggering recursive behavior. The other cases are calling or returning from a function. This is to ensure the following say consistent.
f1(): x = MetaVar() return x
f2(): return MetaVar()
In f1 the return function evaluates if its return argument is the result of a metavar __getself__ call and if so, returns the metavar instead.
This is all done behind what is essentially if (x != NULL) code blocks in c, so that the runtime hit on any code that does not use this feature is kept to a minimum.
On Thu, Jun 27, 2019 at 9:41 AM Chris Angelico email@example.com wrote:
On Thu, Jun 27, 2019 at 11:11 PM Steven D'Aprano firstname.lastname@example.org wrote: >
On Thu, Jun 27, 2019 at 12:46:58AM +1000, Chris Angelico wrote:
There are many things that can be implemented with dunders, yes, but in Python, I would expect these two functions to behave identically:
def f1(x): return frob(x).spam
def f2(x): f = frob(x) s = f.spam return s
This correlation is critical to sane refactoring.
I'm not convinced that this is going to change under the proposal. Since neither f nor s already exist, they cannot overload assignment. Unless something in Nate's proposal is quite different from earlier concrete proposals, I don't think this is a slam-dunk criticism. I think that it is a problem is theory but not in practice.
That would be true if the proposal were only for __setself__, but the __getself__ part makes things more complicated. I'm not 100% sure because I don't fully understand the proposal, but if the object returned by frob(x) has a __getself__ method, I think it would be called in f2 but NOT in f1 (because referencing the name "f" triggers the get, whereas simply chaining ".spam" onto the end of the function call doesn't).
Does that change your view of it?
Python-ideas mailing list -- email@example.com To unsubscribe send an email to firstname.lastname@example.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://email@example.com/message/TK3EFW... Code of Conduct: http://python.org/psf/codeofconduct/
-- Nate Lust, PhD. Astrophysics Dept. Princeton University