Если исправление обезьяны разрешено и в Ruby и в Python, почему это более спорно в Ruby?

Я один из сопровождающих d3fc - к сожалению, на данный момент мы не поддерживаем это. Я поднял вопрос:

https://github.com/d3fc/d3fc/issues/1246

Мы рассмотрим, можем ли мы добавить особенности.

15
задан Paul Dexter 4 April 2009 в 17:54
поделиться

8 ответов

Как Python программист, у которого был вкус Ruby (и любит его), я думаю, что существует своего рода ироническая параллель к тому, когда Python начинал становиться популярным.

C и программисты Java 'колотил' бы Python, указывая, что это не был реальный язык, и что динамический характер его типов будет опасен, и позволит людям создавать 'плохой' код. Поскольку Python стал более популярным, и преимущества его времени быстрой разработки стали очевидными, не говоря уже о менее подробном синтаксисе:

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

мы начали видеть, что некоторые более динамические функции появляются в более поздних версиях Java. При автоупаковке и - распаковывание делает это менее неприятным для контакта с примитивами, и Дженерики позволяют нам кодировать однажды и применять его ко многим типам.

Именно с некоторым развлечением я видел одну из ключевых гибких функций Ruby – Исправление Обезьяны, рекламируясь как опасный толпой Python. Запустив обучающий Ruby студентам в этом году, я думаю, что способность 'зафиксировать' реализацию существующего класса, даже тот, который является частью системы, очень мощна.

Несомненно, можно завинтить плохо, и программа может отказать. Я могу segfault в C довольно легко, также. И приложения Java могут умереть пылающей смертью.

Истина, я вижу, что Обезьяна Исправляет, поскольку следующие вступают динамичные и метапрограммирование. Забавный, так как это было вокруг начиная с Smalltalk.

16
ответ дан 30 November 2019 в 23:51
поделиться

Это - техника, менее искусная в Python, частично потому что "базовые" классы в Python (реализованные в C) не являются действительно модифицируемыми. В Ruby, с другой стороны, из-за пути это реализовано внутренне (не лучше, просто отличающийся) примерно, что-либо может быть изменено динамично.

Философски, это - что-то, что имеет тенденцию быть осужденным в сообществе Python, отчетливо меньше в мире Ruby. Я не знаю, почему Вы утверждаете, что это более спорно (можно ли связаться с авторитетной ссылкой?) - мой опыт состоял в том, что исправление обезьяны является принятой техникой, если тот, где пользователь должен знать о возможных последствиях.

21
ответ дан 30 November 2019 в 23:51
поделиться

Языки могли бы разрешить его, но никакое сообщество не потворствует практике. Monkeypatching не потворствуют ни на одном языке, но Вы слышите об этом чаще в Ruby, потому что форма открытого класса, который он использует, делает его очень, очень легким к monkeypatch класс и из-за этого, это более приемлемо в сообществе Ruby, но все еще осужденное. Monkeypatching просто не так распространен или как легкий в Python, который является, почему Вы не услышите те же аргументы против него в том сообществе. Python не делает ничего, что Ruby не делает для предотвращения практики.

Причина, которую Вы слышите/читаете об этом чаще в Ruby, состоит в том что это в Ruby:

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

даст Вам класс, который содержит два метода, foo и bar, тогда как это в Python:

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

оставит Вас с классом, который только содержит метод bar, поскольку переопределение класса ударяет предыдущее определение полностью. К monkeypatch в Python на самом деле необходимо записать это:

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

который более тверд, чем версия Ruby. Тот один делает код Ruby намного легче к monkeypatch, чем код Python.

16
ответ дан 30 November 2019 в 23:51
поделиться

"Python включает различные типы гарантий для уменьшения рисков этой функции?"

Да. Сообщество отказывается делать это. Гарантия является совершенно социальной.

13
ответ дан 30 November 2019 в 23:51
поделиться

На самом деле в Python немного более трудно изменить основные типы.

Например, вообразите, что Вы переопределяете целое число.

Ruby:

class Fixnum 
   def *(n)
      5 
   end 
end

Теперь 2*2 урожая 5.

Python:

>>> class int(int):
    def __mul__(self, x):
        return 5


>>> 2*2
4
>>> int(2)*int(2)
5
3
ответ дан 30 November 2019 в 23:51
поделиться

В Python, любой литерал ("", {}, 1.0, и т.д.), создает экземпляр стандартного класса, даже если Вы попробовали к monkeypatch его и переопределили соответствующий класс в Вашем пространстве имен.

Это просто не будет работать, как Вы предназначили:

class str():
    # define your custom string type
    ...

a = "foo"      # still a real Python string
a = str("foo") # only this uses your custom class
3
ответ дан 30 November 2019 в 23:51
поделиться

Я думаю, что исправление обезьяны должно только использоваться в качестве последнего решения.

Обычно Python программисты знают, как класс или метод ведут себя. Они знают, что класс xxx делает вещи определенным способом.

Когда Вы патч обезьяны класс или метод, Вы изменяетесь, это - поведение. Другие Python программисты, использующие этот класс, могут быть очень удивлены, ведет ли тот класс себя по-другому.

Нормальный способ сделать вещи разделяет на подклассы. Тем путем другие программисты знают, что используют другой объект. Они могут использовать исходный класс или подкласс, если они принимают решение.

2
ответ дан 30 November 2019 в 23:51
поделиться

Если Вы хотите сделать некоторое исправление обезьяны в Python, это относительно легко, пока Вы не изменяете встроенный тип (интервал, плавание, ул.).

class SomeClass:
    def foo(self):
        print "foo"

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

Это добавит метод панели к SomeClass, и даже существующие экземпляры того класса могут использовать тот введенный метод.

1
ответ дан 30 November 2019 в 23:51
поделиться