On 2021-06-22 3:43 p.m., Brendan Barnwell wrote: > On 2021-06-22 05:14, Chris Angelico wrote: >> Fair point. However, I've worked with a good number of languages that >> have some notion of object methods, and generally, an object has or >> doesn't have a method based on what the object*is*, not on who's >> asking. > > I agree, and this is the aspect of the proposal that most confuses > me. I still can't understand concretely what is being proposed, > though, so I'm not sure I even understand it. Can someone clarify? > Suppose I have this > > ***** > ### file1.py > @extend(list) > def len2(self): > return len(self)**2 > > ### file2.py > # or whatever I do to say "I want to use extensions to list defined in > file1" > from file1 extend list > > def coolness(some_list): > return some_list.len2() + 1 > > my_list = [1, 2, 3] > print("My list len2:", my_list.len2()) > print("My list coolness:", coolness(my_list)) > > ### file3.py > import file2 > > other_list = [1, 2, 3, 4] > print("Other list len2:", other_list.len2()) > print("other list coolness:", file2.coolness(other_list)) > print("My list len2 from outside:", file2.my_list.len2()) > print("My list coolness from outside:", file2.coolness(file2.my_list)) > ***** > > What exactly is supposed to happen here if I run file3? file2 > declares use of file1's extensions. file2 does not. But file3 uses a > function in file2 that makes use of such extensions. Who sees the > extension? >
NameError, value, NameError, value, respectively. > The list object my_list in file2 is the same object accessed as > file2.my_list in file3. Likewise coolness and file2.coolness. It is > going to be super confusing if calling the same function object with > the same list object argument gives different results depending on > which file you're in. Likewise it's going to be confusing if the same > list object sometimes has a .len2 method and sometimes doesn't. It isn't the list object that has the extension method. > > But if it doesn't work that way, then it would seem to mean either > every module sees the extensions (even if they didn't opt in), or else > my_list in file2 is not the same object as file2.my_list in file3. > And that would be even worse. (In this example it may seem okay > because you can ask why I would call len2 from file3 if I didn't want > to use it. But what if the extension is an override of an existing > method? Is that not allowed?) > > In addition, if there is a difference between my_list and > other_list, then that apparently means that the syntax for lists now > does something different in the two files. This is maybe the most > reasonable approach, since it's at least remotely reminiscent of a > __future__ import, which changes syntactic behavior. But what exactly > is the difference between the two objects here? Are both objects > lists? If they are, then how can they have different methods? If > they're not, then what are they? > > Most __future__ imports don't work like this. Maybe the closest > thing is the generator_stop one, but at least that places a flag on > the code object to indicate the difference. Would "extended lists" > have some kind of magic attribute indicating which extensions they're > using? That may have been marginally acceptable in the case of PEP > 479, which was essentially a bugfix, and set the attribute on code > objects which are an obscure internal data structure. But allowing > this kind of thing for "user-facing" objects like lists would create a > profusion of different list objects with different behavior depending > on some combination of attributes indicating "what extends me" --- or, > even worse, create different behavior without any such overt > indication of which extensions are in use for a given object. > > The idea that the file in which code is written would somehow > determine this type of runtime behavior seems to me to break my > assumption that by knowing an object's identity I should have all the > information I need to know about how to use it. Some of the posts > earlier in this thread seem to suggest that somehow the module where > something was defined (something --- not sure what --- maybe the > object with the extended method? maybe the extended method itself?) > would somehow get a hook to override attribute access on some objects > (again, not sure which objects). > > That to me is the exact opposite of encapsulation. Encapsulation > means the object itself contains all its behavior. If there is some > getattr-like hook in some other module somewhere that is lying in wait > to override attribute access on a given object "only sometimes" then > that's not encapsulation at all. It's almost as bad as the infamous > COME FROM statement! > > Existing mechanisms like __getattribute__ are not parallel at all. > When you know an object's identity, you know its MRO, which tells you > all you need to know about what __getattribute__ calls might happen. > You don't need to know anything about where the object "came from" or > what file you're using it in. But it seems with this proposal you > would need to know, and that's kind of creepy to me. > Think about it like this, extension methods give you the ability to make imported functions that look like this: foo(bar, baz) look like this instead: bar.foo(baz) That's all there is to them. They're just a lie to change how you read/write the code. Some languages have an whole operator that has a similar function, where something like bar->foo(baz) is sugar for foo(bar, baz). The OP doesn't specify any particular mechanism for extension methods, so e.g. making the dot operator be implemented by a local function in the module, which delegates to the current attribute lookup mechanism by default, would be perfectly acceptable. It's like deprecating the existing dot operator and introducing a completely different one that has nothing to do with attribute lookup! _______________________________________________ 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/VWGTUNYXDQ3CYYRNL7Z3UCSVDM6IDAMJ/ Code of Conduct: http://python.org/psf/codeofconduct/