
On Fri, Jun 24, 2022 at 5:38 AM Chris Angelico <rosuav@gmail.com> wrote:
On Fri, 24 Jun 2022 at 16:34, Joao S. O. Bueno <jsbueno@python.org.br>
wrote:
On Fri, Jun 24, 2022 at 1:06 AM Chris Angelico <rosuav@gmail.com> wrote:
How much benefit would this be? You're proposing a syntactic construct for something that isn't used all that often, so it needs to be a fairly dramatic improvement in the cases where it _is_ used.
Excuse-me Who is the "you" you are referring to in the last paragraphs? (honest question)
I am not proposing this - the proto-pep is David Mertz' .
You, because you're the one who devised the version that I was responding to. His version is a much more in-depth change, although it has other issues.
ok.
I just pointed out that the language, as it is today,can handle the inner part of the deferred object, as it is.
Yes, but with the limitations that I described.
Indeed - I don't want to argue about that, just point out that the natural way things work in Python as is, some of those limitations do not apply.
(if one just adds all possible dunder methods to your proxy example above, for example)
I still don't understand why you treat dunder methods as special here. Are you, or are you not, relying on __getattribute__? Have you taken tp_* slots into account? I had not thought about tp_*slots - I am just considering pure Python code: any slot which does not alias to a visible dunder method would map to the proxy instead, in a straightforward way for one looking only at the Python code. Maybe some of the not mapped slots might cause some undesired effects, and should trigger the resolve as well.
. The reason I am treating dunder attributes as special is simply because it is what cPython does when resolving any operator with an object - any other attribute access, from Python code, goes through __getattribute__, but the code path triggered by operators (+, -, ..., not, len, str) does not.
Moreover, there could be an attribute namespace to deal/modify the
so - retrieving the "real" object could be trivial. (the original would actually be retrieved in _any_ operation with with the object that would make use of its dunder attributes - think "str", or "myobj + 3", since
object the proxy
dunder would forward the operation to the wrapped object corresponding method.
Okay, here's an exercise for you. Given any function f(), ascertain whether these two calls returned the same object:
x = f() y = later f()
You do not know what kind of object it is. You just have to write the code that will answer the question of whether the second call to f() returned the exact same object as the first call. Calling str() on the two objects is insufficient, for instance. Calling id(y) is not going to touch any of y's dunder methods - it's just going to return the ID of the proxy, so it'll always show as different.
It won't work, indeed. unless there are reserved attributes that would cause the explicit resolve. Even if it is not given, and there is no way for a "is" comparison, this derives from the natural usage of the proxy, with no exceptional behaviors needed. The proxy is not the underlying object, after all. And not even a convention such as a ".__deferred_resolve__" call could solve it: the simpler path I pointed out does not involve "in place attribute substitution". But such a method could return resolve and return the wrapped object, and then: `(z := resolve(y)) is x`, would work , as well as id(resolve(y)) == id(x), but "y"would still be the proxy <- no magic needed, and that is the point I wanted to bring. A similar proxy that is used in day to day coding is a super() instance, and I never saw one needing `super(cls, instance) is instance` to be true. [...]
Then you are not talking about the same thing at all. You're talking about a completely different concept, and you *are* the "you" from my last paragraphs.
I see. I've stepped in because that approach worked _really_ well, and I don't think it is _all_ that different from the proposal on the thread, and is instead a middleground not involving "inplace object mutation", that could make something very close to that proposal feasible. Maybe I'd be more happy to see a generic way to implement "super proxys" like these in a less hacky way, and then those could be used to build the deferred objects as in this proposal, than this specific implementation. In the example project itself, Lelo, the proxys are used to calculate the object in a subprocess, rather than just delaying their resolve in-thread.
I just wrote because it is something I made work before - and if there
are indeed
uses for it, the language might not even need changes to support it beyond an operator keyword.
Yes, you've done something that is broadly similar to this proposal, but like every idea, has its own set of limitations. It's easy to say "I did something different from what you did, and it doesn't require language support", but your version of the proposal introduces new problems, which is why I responded to them.
Alright - but the only outstanding problem is the "is" and "id"comparison - I am replying still because I have the impression you had not grokked the main point: at some point, sooner or later, for any object in Python, one of the dunder methods _will_ be called (except for identity comparison, if one has it as an "end in itself"). Be it for printing, serializing, or being the target of a unary or binary operator. This path can be hooked to trigger the deferred resolve in the proposal in this thread. That said, I am not super in favor of it being in the language, and I will leave that for other people to discuss. So, thank you for your time. Really! js -><-
ChrisA Code of Conduct: http://python.org/psf/codeofconduct/