4 ms·
Eh, this works fine (on Python 2.7): class A(object): def foo(self): return 'foo' a = A() a.foo() # returns 'foo' a.__c
by JoachimSchipper 8y ago
Eh, this works fine (on Python 2.7):
class A(object):
def foo(self):
return 'foo'
a = A()
a.foo() # returns 'foo'
a.__class__.foo = lambda self: 'bar'
A().foo() # new instance (!) returns 'bar'
You're correct for list ("TypeError: can't set attributes of built-in/extension type 'list'"), but that's more a implementation limitation than a principled stance.
- rsj_hn 8y agoYou just looked up the class of a which is A and then you patched the foo method in the class definition of A. This is no different than you saying A.foo = lambda ... But what you can't do in Python is monkey patch a method to a class for which you don't have a reference. Try it. This is not an "implementation limitation", it is because Python is not a prototype language, so you can't monkey patch what it means to "call a function" for every method in every class because there is no "Function" object that is a prototype of all method calls in Python that plays a similar role to Function in Javascript. Similarly you can't patch "Object" de-reference and change the behavior of every single object de-reference. Those prototype chains are not exposed to you. In javascript you can override methods of classes which you can't reference. That's huge. Imagine one person creates an object with a foo method, and someone else changes what it means for all objects of any class to call any method. Think about what you have to audit to determine what the behavior of foo is -- in Python, you just need to audit anything that has a reference to the class where foo is defined. In javascript, you need to know what all the code is doing. That's a big difference.
- likpok 8y agoPython did have some scheme to do something like this. If you were using gevent, you needed to call gevent.monkey_patch() to override all the network calls that you were making under the hood, so that they would happen on the event loop. Yes, gevent did have a reference to the classes it was patching, but it still made pretty deep changes to a program. It was janky and has been replaced several times by other async frameworks. It doesn't go as far as javascript to be sure, but it is sort of what you're suggesting.
- rsj_hn 8y agoYeah, the issue isn't monkey patching per se, but lack of isolation. Javascript just doesn't support the concept of a "module" that cannot interfere with globals via side effects or is somehow restricted to interacting with the rest of the system via a clearly defined API that can be checked without reading all the code in the module. That, combined with the fact that people load thousands of modules just to do simple short programs, makes it very hard to reason about javascript code efficiently. You can try to hide global references from a javascript module, for example by using "with", but you will always have access to things like constructor() which will give you the raw window, so you can't hide a reference to Window even if you shadow Window via "with". Even ignoring that, you still can overwrite builtins from anywhere in the code, thus effectively changing the shared runtime. There is no notion of scoped builtins -- e.g. overwrite builtins all you want, but just in your own scope. That lack of isolation is the problem, not monkey patching your own objects.