Ruby と Python の両方でモンキー パッチが許可されているのに、Ruby ではなぜより物議を醸すのでしょうか?
-
23-08-2019 - |
質問
Ruby についての多くの議論で、人々がこの言語について懸念を表明しているのを聞いてきましたが、モンキーパッチの問題が彼らの主な懸念事項の 1 つとして取り上げられました。
ただし、Python 言語でも同じ議論が許可されていますが、Python のコンテキストで同じ議論がなされるのをほとんど聞きません。
なぜこの区別があるのでしょうか?
Python には、この機能のリスクを最小限に抑えるためのさまざまな種類の保護手段が含まれていますか?
解決
ルビーの味を持っていた(そしてそれが好き)しているPythonプログラマとして、私はややPythonが人気になり始めたときに皮肉な並列のがあると思います。
CとJavaプログラマは「bashの」Pythonの、それは本当の言語ではなかったことを示すだろう、とその種類の動的な性質は危険なこと、そして人々が「不良」コードを作成できるようになるという。 Pythonはより多くの人気となった、とその急速な開発時間の利点は少ない冗長な構文はもちろんのこと、明らかになったようます:
// Java
Person p = new Person();
# Python
p = Person()
我々はいくつかのよりダイナミックな機能は、Javaのそれ以降のバージョンで表示され始めました。オートボクシングとプリミティブに対処することがあまり面倒作る-unboxing、およびジェネリックは私たちが一度コーディングと多くの種類に適用することができます。
モンキーパッチ適用、Pythonの群衆によって危険として宣伝されている -これは、私がルビーの主要柔軟な機能の一つを見て、いくつかの遊園地とありました。今年は学生にルビーを教え始めた、私は、システムの一部であっても1、既存のクラスの実装「修正」にできることは非常に強力であること。
だと思います確かに、あなたはひどく台無しにすることができますし、プログラムがクラッシュすることができます。私も、かなり簡単にCでセグメンテーションフォールトすることができます。そして、Javaアプリケーションは、死を燃える死ぬことができます。
真実は、私は、ダイナミックとメタプログラミングの次のステップとして、モンキーパッチ適用を参照してください、です。おかしい、それはSmalltalkの以来の周りされているので。
他のヒント
この技術以下を実践することPythonで"コア"の授業Python(その実施C)めったに変更可能です。Rubyので、その実施内(ないような)って修正できます。
--ね、"構築"と"破壊"とい傾向にあるの延におけるPythonを、明確に従うことを選択しない限り、のRubyです。なぜだかよくわかりませんであると主張することでより多くの論議を呼んだのですリンクの権威ある。) -私の経験しているサル-パッチが受け入れの手法の場合、ユーザーを知っておく必要があるので結果をもたらす。
言語によってはそれが許可されているかもしれませんが、どのコミュニティもその慣行を容認していません。どちらの言語でもモンキーパッチは容認されていませんが、Ruby ではそのことをよく耳にします。これは、Ruby で使用されるオープン クラスの形式により、クラスにモンキーパッチを適用することが非常に簡単になるためです。 Rubyコミュニティではより受け入れられていますが、依然として眉をひそめています. 。モンキーパッチは Python ではそれほど普及していないか、簡単ではありません。そのため、そのコミュニティではモンキーパッチに対する同じような議論を聞くことはありません。Python は、Ruby と同様に、この行為を阻止することは何もしません。
Ruby でこのことについて頻繁に聞いたり読んだりする理由は、Ruby では次のようなことが挙げられるためです。
class MyClass
def foo
puts "foo"
end
end
class MyClass
def bar
puts "bar"
end
end
2 つのメソッドを含むクラスが得られます。 foo
そして bar
, 一方、Python では次のようになります。
class MyClass:
def foo(self):
print "foo"
class MyClass:
def bar(self):
print "bar"
メソッドのみを含むクラスが残ります bar
, クラスの再定義は以前の定義を完全に上書きするためです。Python でモンキーパッチを適用するには、実際には次のように記述する必要があります。
class MyClass:
def foo(self):
print "foo"
def bar(self):
print "bar"
MyClass.bar = bar
Ruby 版よりも難しいです。それだけでも、Ruby コードは Python コードよりもはるかに簡単にモンキーパッチを適用できます。
「Pythonは、この機能のリスクを最小限に抑えるためにセーフガードの異なる種類が含まれていますか?」
はい。コミュニティはそれを行うことを拒否します。セーフガードは完全に社会的である。
実際にPythonでそれが基本的なタイプを変更するには、少し難しくなります。
たとえば、あなたが整数を再定義することを、想像します。
ルビーます:
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
Pythonでは、任意のリテラル(""
、{}
、1.0
、など)は、あなたがそれをモンキーパッチしようとしたし、あなたの名前空間に対応するクラスを再定義した場合でも、標準クラスのインスタンスを作成します。
それはちょうどあなたが意図したどのように動作しません。
class str():
# define your custom string type
...
a = "foo" # still a real Python string
a = str("foo") # only this uses your custom class
私は猿のパッチ適用が唯一の最後の解決策として使用されるべきだと思います。
通常のPythonプログラマはどのようにクラスやメソッドの振る舞いを知っています。彼らはクラスのxxxは、特定の方法で物事をやっていることを知っています。
あなたは猿クラスやメソッドにパッチを適用すると、、あなたはそれが行動だ変化しています。そのクラスが異なる動作をされている場合、このクラスを使用して、他のPythonプログラマは非常に驚くことができます。
物事の通常の方法は、サブクラスです。こうすることで、他のプログラマは、彼らが別のオブジェクトを使用していることを知っています。彼らが選択した場合、彼らは元のクラスまたはサブクラスを使用することができます。
、それは限り、あなたは組み込み型(int型、float型、STR)を変更していないとして、比較的容易である。
class SomeClass:
def foo(self):
print "foo"
def tempfunc(self):
print "bar"
SomeClass.bar = tempfunc
del tempfunc
これは工assにバーメソッドを追加しますと、そのクラスのも、既存のインスタンスは、その注入されたメソッドを使用することができます。