If monkey patching is permitted in both Ruby and Python, why is it more controversial in Ruby?

前端 未结 8 1390
一向
一向 2021-02-05 12:34

In many discussions I have heard about Ruby in which people have expressed their reservations about the language, the issue of monkey patching comes up as one of their primary c

相关标签:
8条回答
  • 2021-02-05 12:37

    I think that monkey patching should only be used as the last solution.

    Normally Python programmers know how a class or a method behave. They know that class xxx is doing things in a certain way.

    When you monkey patch a class or a method, you are changing it's behavior. Other Python programmers using this class can be very surprised if that class is behaving differently.

    The normal way of doing things is subclassing. That way, other programmers know that they are using a different object. They can use the original class or the subclass if they choose to.

    0 讨论(0)
  • 2021-02-05 12:40

    As a Python programmer who has had a taste of Ruby (and likes it), I think there is somewhat of an ironic parallel to when Python was beginning to become popular.

    C and Java programmers would ‘bash’ Python, stating that it wasn't a real language, and that the dynamic nature of its types would be dangerous, and allow people to create ‘bad’ code. As Python became more popular, and the advantages of its rapid development time became apparent, not to mention the less verbose syntax:

    // Java
    Person p = new Person();
    
    # Python
    p = Person()
    

    we began to see some more dynamic features appear in later versions of Java. Autoboxing and -unboxing make it less troublesome to deal with primitives, and Generics allow us to code once and apply it to many types.

    It was with some amusement that I saw one of the key flexible features of Ruby – Monkey Patching, being touted as dangerous by the Python crowd. Having started teaching Ruby to students this year, I think that being able to ‘fix’ the implementation of an existing class, even one that is part of the system, is very powerful.

    Sure, you can screw up badly and your program can crash. I can segfault in C pretty easily, too. And Java apps can die flaming death.

    The truth is, I see Monkey Patching as the next step in dynamic and meta-programming. Funny, since it has been around since Smalltalk.

    0 讨论(0)
  • 2021-02-05 12:41

    In Python, any literal ("", {}, 1.0, etc) creates an instance of the standard class, even if you tried to monkeypatch it and redefined the corresponding class in your namespace.

    It just won't work how you intended:

    class str():
        # define your custom string type
        ...
    
    a = "foo"      # still a real Python string
    a = str("foo") # only this uses your custom class
    
    0 讨论(0)
  • 2021-02-05 12:44

    Actually in Python it's a bit harder to modify basic types.

    For example imagine, that you redefine integer.

    Ruby:

    class Fixnum 
       def *(n)
          5 
       end 
    end
    

    Now 2*2 yields 5.

    Python:

    >>> class int(int):
        def __mul__(self, x):
            return 5
    
    
    >>> 2*2
    4
    >>> int(2)*int(2)
    5
    
    0 讨论(0)
  • 2021-02-05 12:45

    The languages might permit it, but neither community condones the practice. Monkeypatching isn't condoned in either language, but you hear about it more often in Ruby because the form of open class it uses makes it very, very easy to monkeypatch a class and because of this, it's more acceptable in the Ruby community, but still frowned upon. Monkeypatching simply isn't as prevalent or as easy in Python, which is why you won't hear the same arguments against it in that community. Python does nothing that Ruby doesn't do to prevent the practice.

    The reason you hear/read about it more often in Ruby is that this in Ruby:

    class MyClass
      def foo
        puts "foo"
      end
    end
    
    class MyClass
      def bar
        puts "bar"
      end
    end
    

    will give you a class that contains two methods, foo and bar, whereas this in Python:

    class MyClass:
        def foo(self):
            print "foo"
    
    class MyClass:
        def bar(self):
            print "bar"
    

    will leave you with a class that only contains the method bar, as redefinition of a class clobbers the previous definition completely. To monkeypatch in Python, you actually have to write this:

    class MyClass:
        def foo(self):
            print "foo"
    
    def bar(self):
        print "bar"
    MyClass.bar = bar
    

    which is harder than the Ruby version. That alone makes Ruby code much easier to monkeypatch than Python code.

    0 讨论(0)
  • 2021-02-05 12:48

    If you want to do some monkey patching in Python, it is relatively easy, as long as you are not modifying a built-in type (int, float, str).

    class SomeClass:
        def foo(self):
            print "foo"
    
    def tempfunc(self):
        print "bar"
    SomeClass.bar = tempfunc
    del tempfunc
    

    This will add the bar method to SomeClass and even existing instances of that class can use that injected method.

    0 讨论(0)
提交回复
热议问题