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 -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/ELFA6AQU77UQVJKWJWCY4T45HI6PDMEJ/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to