1. ホーム
  2. パイソン

[解決済み】RubyにあってPythonにないもの、またその逆は何ですか?

2022-04-18 03:32:58

質問

Python対Rubyの議論はたくさんありますが、私はどれも全く役に立たないと思っています。なぜなら、Xという機能がY言語で最悪なのか、あるいはY言語にはXがない、しかし実際にはあるのだという主張が中心になっているからです。私はなぜPythonが好きなのかもよく知っていますが、それも主観的なもので、私と同じような開発の好みを持っているとは限らないので、選ぶ人の参考にはならないでしょう。

そこで、客観的に違いを列挙してみると面白いのではないでしょうか。だから、「Pythonのラムダはクソだ」なんてことはありません。その代わり、RubyのlambdasにできてPythonのlambdasにできないことを説明してください。主観は入れない。サンプルコードもいい

一つの答えにいくつもの違いがあるのはやめてください。そして、正しいとわかっているものは上に投票し、間違っている(あるいは主観的である)とわかっているものは下に投票してください。また、構文の違いもおもしろくありません。PythonはRubyが括弧や末尾でやっていることをインデントでやっているし、@をPythonではselfと呼ぶことも知っています。

UPDATE: コミュニティWikiになったので、大きな違いをここに追加することができるようになりました。

Rubyでは、クラス本体にクラス参照を持つ

Rubyでは、クラス本体ですでにクラス(self)への参照を持っています。Pythonでは、クラスの構築が終わるまで、クラスへの参照はありません。

一例です。

class Kaka
  puts self
end

この場合の self はクラスであり、このコードは "Kaka" と出力されます。Pythonではクラス名を出力したり、クラス定義本体からクラスにアクセスする方法はありません(メソッド定義以外では)。

Rubyではすべてのクラスがミュータブル

これにより、コア・クラスの拡張を開発することができます。 以下は、railsの拡張機能の例です。

class String
  def starts_with?(other)
    head = self[0, other.length]
    head == other
  end
end

Pythonの場合(仮に ''.startswith メソッド)を使用します。

def starts_with(s, prefix):
    return s[:len(prefix)] == prefix

文字列だけでなく、任意のシーケンスに使用できます。これを使うには、インポートする必要があります。 明示的に from some_module import starts_with .

RubyにはPerlのようなスクリプト機能がある

Ruby には第一級の正規表現、$-変数、awk/perl の line by line 入力ループ、その他の機能があり、テキストファイルをつぶしたり、他のプログラムのグルーコードとして機能する小さなシェルスクリプトを書くのに適しています。

Rubyには第一級の連続性がある

callcc文のおかげです。Pythonでは、様々なテクニックで継続を作ることができますが、言語に組み込まれたサポートはありません。

Rubyにはブロックがある

Rubyでは"do"文で複数行の無名関数を作ることができ、doの前にあるメソッドに引数として渡され、そこから呼び出されることになります。Pythonでは、メソッドを渡すか、ジェネレータを使用してこれを行います。

ルビー

amethod { |here|
    many=lines+of+code
    goes(here)
}

Python (RubyのブロックはPythonの異なる構成要素に対応します)。

with amethod() as here: # `amethod() is a context manager
    many=lines+of+code
    goes(here)

または

for here in amethod(): # `amethod()` is an iterable
    many=lines+of+code
    goes(here)

または

def function(here):
    many=lines+of+code
    goes(here)

amethod(function)     # `function` is a callback

興味深いことに、Rubyではブロックを呼び出すための便利な文は"yield"と呼ばれ、Pythonではジェネレータを作成することになるのです。

ルビーです。

def themethod
    yield 5
end

themethod do |foo|
    puts foo
end

Pythonです。

def themethod():
    yield 5

for foo in themethod():
    print foo

原理は違えど、結果は驚くほど似ています。

Rubyは関数型(パイプ型)プログラミングをより簡単にサポートします。

myList.map(&:description).reject(&:empty?).join("\n")

Pythonです。

descriptions = (f.description() for f in mylist)
"\n".join(filter(len, descriptions))

Pythonには組み込みのジェネレータがあります(前述のようにRubyのブロックのように使用します)。

Pythonは言語内でジェネレータをサポートしています。Ruby 1.8 では、ブロックからジェネレータを作成するために、連続を使用するジェネレータモジュールを使用することができます。あるいは、block/proc/lambdaを使うこともできます! さらにRuby 1.9では、ファイバーはジェネレータであり、ジェネレータとして使うことができますし、Enumeratorクラスは組み込みのジェネレータとなっています。 4

docs.python.org には、このジェネレータの例があります。

def reverse(data):
    for index in range(len(data)-1, -1, -1):
        yield data[index]

上記のブロックの例と対比してください。

Pythonは名前空間を柔軟に扱える

Rubyでは、ファイルをインポートする際に require そのファイルで定義されたすべてのものは、グローバルな名前空間に入ってしまうのです。これは、名前空間汚染の原因となる。これを解決するのがRubysのモジュールです。しかし、モジュールで名前空間を作ると、含まれるクラスにアクセスするために、その名前空間を使わなければなりません。

Pythonでは、ファイルはモジュールであり、その含まれる名前をインポートするには from themodule import * もし必要なら、名前空間を汚染することになります。しかし、選択した名前だけをインポートすることもできます。 from themodule import aname, another または、単純に import themodule で名前にアクセスし themodule.aname . 名前空間のレベルを上げたい場合は、パッケージと呼ばれる、モジュールと __init__.py ファイルを作成します。

Pythonにはdocstringがある

Docstringsは、モジュール、関数、メソッドに付加される文字列で、以下のようなことが可能です。 実行時にイントロスペクトされます。これは、helpコマンドのようなものを作成するのに役立ちます。 を自動生成します。

def frobnicate(bar):
    """frobnicate takes a bar and frobnicates it

       >>> bar = Bar()
       >>> bar.is_frobnicated()
       False
       >>> frobnicate(bar)
       >>> bar.is_frobnicated()
       True
    """

Rubyの同等のものはjavadocsと似ていて、メソッドの中ではなく、メソッドの上に位置しています。 これらは実行時に 1.9 の Method#source_location を使ってファイルから取得することができます。 使用例

Pythonには多重継承がある

Rubyではありません("on purpose" -- Rubyのウェブサイトをご覧ください。 Rubyではどうなっているかはこちらをご覧ください。 ). しかし、モジュールの概念を抽象クラスの一種として再利用しています。

Pythonはリスト/ディクショナリを持っている

Pythonです。

res = [x*x for x in range(1, 10)]

ルビーです。

res = (0..9).map { |x| x * x }

Pythonです。

>>> (x*x for x in range(10))
<generator object <genexpr> at 0xb7c1ccd4>
>>> list(_)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

ルビーです。

p = proc { |x| x * x }
(0..9).map(&p)

パイソン 2.7+ :

>>> {x:str(y*y) for x,y in {1:2, 3:4}.items()}
{1: '4', 3: '16'}

ルビーです。

>> Hash[{1=>2, 3=>4}.map{|x,y| [x,(y*y).to_s]}]
=> {1=>"4", 3=>"16"}

Pythonにはデコレータがある

Rubyでもデコレータに似たものは作れますし、Pythonほどは必要ないとも言えます。

構文の違い

Ruby ではすべてのスコープを閉じるために "end" または "}" が必要ですが、Python ではホワイトスペースだけが使用されます。 Rubyでは最近、ホワイトスペースだけのインデントを許容する試みがなされています http://github.com/michaeledgar/seamless

解決方法は?

RubyでもPythonでも、クラス定義の中にコードを入れることができます。しかし、Rubyではクラスへの参照(self)があります。Pythonでは、クラスはまだ定義されていないので、クラスへの参照はありません。

一例です。

class Kaka
  puts self
end

この場合の self はクラスで、このコードは "Kaka" と出力されます。Pythonではクラス名を出力したり、クラス定義のボディからクラスにアクセスする方法はありません。