On Thu, Dec 01, 2022 at 03:19:38PM -0700, Anony Mous wrote:

> I'd love to hear a justification -- any justification -- against what I'm
> talking about, because to date, I've never run into one. Many have tried,
> too. :)

What is the `str` interface? Perhaps not the best example, because 
strings have so many methods, but it will do. Under Python's design, we 
know what methods strings have. We absolutely categorically know that if 
`type(obj) is str` then we can rely on a specific interface, namely 47 
methods and 33 dunders.

What is the `str` interface with monkey-patching allowed? It's 
impossible to predict. The string interface depends on which methods 
have been monkey-patched in.

It gets worse if we allow monkey-patching of individual instances as 
well as the entire class. Now you don't necessarily know that two 
strings support the same operations, even if their type is the same.

If you have a string, you don't know whether or not it will support the 
TestDottedQuad method.

These are points of friction that can make the language harder to use. 
How is a beginner supposed to know which methods are native to strings, 
and which are monkey-patched in? Where is `str.TestDottedQuad` 
implemented and documented?

If you have a class and method you are not familiar with, say 
`Widget.frob()`, in a large application you don't know well, how do you 
find where `frob` was added to the class? It could have come from 
anywhere.

What happens if you go to monkey-patch string with TestDottedQuad and 
*some completed unrelated library* has beat you to it and already done 
so? Monkey-patching is safe so long as you are the only one doing it. As 
soon as libraries get in the act, things go down hill very quickly.

These are not insurmountable problems. Python supports powerful 
intraspection tools. Most classes that we write in pure Python, using 
the `class` keyword, support monkey-patching not just the class but 
individual instances as well, and it is considered a feature that most 
classes are extendable in that way. We mostly deal with that feature by 
*not using it*.

The Ruby communittee learned the same lesson: the best way to use 
monkey-patching is to not use monkey-patching.

https://avdi.codes/why-monkeypatching-is-destroying-ruby/

So the ability to monkey-patch classes and instances is considered to be 
feature of marginal usefulness. Sure, sometimes its handy, but mostly it 
just adds complexity.

When it comes to builtins, the deciding factor is that the builtins are 
programmed in C (in CPython, other interpreters may do differently), and 
for speed and efficiency, and immutability, they usually don't include a 
`__dict__` that you can monkey-patch into. The class itself may have a 
read-only mapping proxy rather than a dict you can add items into.

So in principle Python supports monkey-patching, but in practice CPython 
at least typically removes that support from most builtin types for 
efficiency reasons. And because monkey-patching is frowned upon, we 
don't miss it.


> In any case, I wanted that ability because I was doing a lot of interesting
> things to strings, and str was doing a stellar job of making that more
> difficult.

I find that implausible. You can do whatever interesting things you like 
with strings, you just can't use method syntax.

You can't use `mystring.TestDottedQuad()` but you can use 
`TestDottedQuad(mystring)`, which is just a change in order (and one 
character fewer to type).

I suppose the one thing you can't easily do with function syntax is give 
each individual instance its own distinct method. So if you have three 
instances, spam, eggs, cheese, with monkey-patching you can give all 
three instances their own frob() method, each method doing something 
different. But that way leads to chaos.


> Again, explain a danger to a nominal class user that arises due to adding
> NEW, immutable in the current instance, functions/functionality to a class
> that do not alter the existing base functionality. ANY danger.

As I said above, that's fine when you are the only one doing it. But as 
soon as monkey-patching becomes popular, and everyone starts using it, 
then you have to deal with conflicts.

Library A and library B both want to monkey-patch strings with the same 
method. Now you can only use one or the other. If they just used 
functions, they would be fine, because A.TestDottedQuad and 
B.TestDottedQuad live in separate namespaces, but with monkey-patching 
they both try to install into the same namespace, causing a clash.


-- 
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/NM2F743TS4U6WIESVLZQ6MC3IWUCFKEE/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to