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/