On Tue, Jun 22, 2021 at 10:25:33PM +1000, Chris Angelico wrote:
> > If its a problem for getattr, it is a problem for dot syntax, because
> > they are essentially the same thing.
>
> Ahh but that is precisely the problem.
Is it? Don't be shy. Tell us what the problem is and why its a problem.
> > > How is getattr defined?
> >
> > The same as it is defined now, except with some minor tweaks to support
> > extension methods.
>
> Do those tweaks include reaching back into the module that called it?
> How magical will it be?
I thought you agreed that we didn't need to discuss implementation until
we had decided on the desired semantics?
Let's just say it will be a well-defined, totally non-magical
implementation (like everything else in Python) that manages to be
equally efficient as regular attribute access. A high bar to set.
Implementation issues may require us to dial that back a bit, or might
even rule out the concept altogether, but let's start off by assuming
the best and decide on the semantics first.
[...]
> Let me clarify then.
Thank you, that would be helpful.
> We shall assume for the moment that the builtins module does not have
> any extension methods registered. (I suppose it could, but then you
> get all the action-at-a-distance of monkey-patching AND the problems
> of extension methods, so I would hope people don't do this.)
How do you know that the builtins aren't already using extension
methods?
Let's pretend that you didn't know that CPython's implementation was C
rather than C#. Or that C has support for something similar to extension
methods. (I daresay you could simulate it, somehow.) Or that we're
talking about IronPython, for example, which is implemented in C#. I
might tell you that list.sort and list.index are regular methods, and
that list.append and list.reverse are extension methods.
Short of looking at the source code, there would be absolutely no way
for you to tell if I were correct or not.
So if builtins used extension methods, that would be indistinguishable
from builtins not using extension methods.
(To be pedantic: this would only be true if those extension methods were
added at interpreter startup, before the interpreter ran any user code.
Otherwise you could take a snapshot of `dir(list)` before and after, and
inspect the differences.)
To be clear, this is distinct from *a user module* using extension
methods on a builtin type, which is normal and the point of the
exercise.
Do I need to explain the difference between the interpreter using
extension methods as part of the builtins implementation, and user-
written modules ("spam.py") extending builtin classes with extension
types? Because they are completely different things.
> This means that the getattr() function, being a perfectly
> straight-forward function, is not going to see any extension methods.
Does getattr see slots (both C-level and Python)? Yes. Does it see
attributes in instance and class dicts? Yes. Does it see dynamic
attributes that use `__getattr__`? Yes. Does it understand the
descriptor protocol? Yes.
It does everything else dot notation does. Why wouldn't it see extension
methods? (Apart from spite.)
The getattr builtin is just a public interface to whatever internal
function or functions the interpreter uses to look up attributes.
> # whatever the actual syntax is
> @extend(list)
> def in_order(self):
> return sorted(self)
>
> stuff = [1, 5, 2]
> stuff.in_order() # == [1, 2, 5]
> getattr(stuff, "in_order")() # AttributeError
What reason do you have for thinking that would be how it works?
Not a rhetorical question: is that how it works in something like Swift,
or Kotlin?
> Does the getattr function see the extension methods? If so, which?
Yes, and the same ones you would see if you used dot syntax.
> If not, how can getattr return the same thing as attribute lookup
> does?
I think you've just answered your own question. getattr has to return
the same thing as attribute lookup, because if it didn't, it wouldn't be
returning the same thing as attribute lookup, which is getattr's reason
to exist.
> How do you inform getattr of which extension methods it should be looking at?
You don't. You inform the interpreter tha you are opting in to use
extension methods on a type, the interpreter does whatever it needs to
do to make it work (implementation), and then it Just Works™.
> And what about this?
>
> f = functools.partial(getattr, stuff)
> f("in_order")
>
> NOW which extension methods should apply? Those registered here? Those
> registered in the builtins? Those registered in functools?
partial is just a wrapper around its function argument, so that should
behave *exactly* the same as `getattr(stuff, 'in_order')`.
> Yes, monkey-patching *is* cleaner, because the object is the same
> object no matter how you look it up.
Oh for heaven's sake, I'm not proposing changes to Python's object
identity model! Please don't invent bogus objections that have no basis
in the proposal. The id() function and `is` operator will work exactly
the same as they do now. Classes with extension methods remain the same
object. The only difference is in attribute lookups.
> (Oh, and another wrinkle, although a small one: Code objects would
> need to keep track of their modules.
Would they? I'm not seeing the connection between code objects used by
functions and attribute lookups. Perhaps they would, but it's not clear
to me what implementation you are thinking of when you make this
statement.
`getattr` doesn't even have a `__code__` attribute, and neither do
partial objects.
--
Steve
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/ELFA6AQU77UQVJKWJWCY4T45HI6PDMEJ/
Code of Conduct: http://python.org/psf/codeofconduct/