RubyからPythonを学ぶ。相違点と類似点


131

Rubyはよく知っています。私は現在Pythonを学ぶ必要があるかもしれないと信じています。両方を知っている人にとって、2つの概念はどのように類似していて、何が違うのでしょうか。

私はJavaScript学習者向けにLuaを学ぶために書いた入門書に似たリストを探しています。空白の重要性やループ構造などの簡単なものです。nilPythonでの名前、および「真正」と見なされる値。同等のものを使用することが慣用的であるmapeach、またはされてむにゃむにゃ somethingaboutlistcomprehensionsは つぶやくノルムを?

さまざまな回答が得られた場合は、コミュニティWikiにまとめて喜んで提供します。さもなければ、あなたは皆がお互いに戦って戦うことができ、真の包括的なリストを作成することができます。

編集:明確にするために、私の目標は「適切」で慣用的なPythonです。に相当するPython injectがあっても、リストを反復して結果を蓄積する一般的な機能を実現するためのより良い/異なる方法があるため、誰もそれを使用していない場合、私はあなたがどうやっているかを知りたいです。おそらく、私はこの質問を一般的な目標のリストで更新し、Rubyでそれらをどのように達成するか、そしてPythonで同等のものは何かを尋ねます。


1
私が読んだ唯一のものはc2.com/cgi/wiki?PythonVsRubyでした、私は本当に自分とインデントが好きではありませんが、それに慣れました:)
Saif al Harthi

1
関連:stackoverflow.com/questions/1113611/…(それが重複しているかどうかはよくわかりません。その質問では同等のものがないためです)。

19
@SilentGhost私は強く同意しません。私は「言語間で何が同じで、何が違うのか」と尋ねています。以下の多くの回答が示すように、これには非常に明確で役立つ回答が可能です。
Phrogz、2011年

3
@Phrogz:私はそれを見て、質問を答えられないようにします。
SilentGhost 2011年

2
@Phrongz-あなたが投稿したメタトピックについて私が言ったことをエコーするには、この質問の問題は、問題のスペースが大きすぎることです。1つの質問だけではトピックが大きすぎます。2つの言語の間には何千もの違いがあります。
アダムデービス

回答:


153

ここにいくつかの重要な違いがあります:

  1. Rubyにはブロックがあります。Pythonではありません。

  2. Pythonには関数があります。Rubyにはありません。Pythonでは、任意の関数またはメソッドを取得して、それを別の関数に渡すことができます。Rubyでは、すべてがメソッドであり、メソッドを直接渡すことはできません。代わりに、それらを渡すためにProcでラップする必要があります。

  3. RubyとPythonはどちらもクロージャーをサポートしていますが、方法は異なります。Pythonでは、別の関数内に関数を定義できます。内部関数には、外部関数からの変数への読み取りアクセス権がありますが、書き込みアクセス権はありません。Rubyでは、ブロックを使用してクロージャを定義します。クロージャーは、外部スコープからの変数への完全な読み取りおよび書き込みアクセス権を持っています。

  4. Pythonにはリストの内包表記があり、かなり表現力があります。たとえば、数値のリストがある場合、次のように書くことができます

    [x*x for x in values if x > 15]

    15より大きいすべての値の二乗の新しいリストを取得するには、Rubyで次のように記述する必要があります。

    values.select {|v| v > 15}.map {|v| v * v}

    Rubyコードはコンパクトに感じられません。また、最初に値の配列を15より大きい値を含む短い中間配列に変換するため、それほど効率的ではありません。次に、中間配列を取得し、中間の二乗を含む最終配列を生成します。次に、中間配列が破棄されます。したがって、Rubyは計算中にメモリ内に3つの配列を作成します。Pythonでは、入力リストと結果のリストのみが必要です。

    Pythonも同様のマップ内包を提供します。

  5. Pythonはタプルをサポートしています。Rubyにはありません。Rubyでは、タプルをシミュレートするために配列を使用する必要があります。

  6. Rubyはswitch / caseステートメントをサポートしています。Pythonではありません。

  7. Rubyは標準のexpr ? val1 : val2三項演算子をサポートしています。Pythonではできません。

  8. Rubyは単一継承のみをサポートします。複数の継承を模倣する必要がある場合は、モジュールを定義し、ミックスインを使用してモジュールメソッドをクラスにプルできます。Pythonは、モジュールミックスインではなく多重継承をサポートしています。

  9. Pythonは単一行のラムダ関数のみをサポートしています。ラムダ関数の一種/一種であるRubyブロックは、任意に大きくすることができます。このため、Rubyコードは通常、Pythonコードよりも機能的なスタイルで記述されています。たとえば、Rubyでリストをループするには、通常、

    collection.each do |value|
      ...
    end

    ブロックは、に渡される関数と非常によく似ていますcollection.each。Pythonで同じことを行う場合は、名前付きの内部関数を定義し、それを各メソッドのコレクションに渡す必要があります(リストがこのメソッドをサポートしている場合)。

    def some_operation(value):
      ...
    
    collection.each(some_operation)

    それはあまりうまく流れません。したがって、通常、Pythonでは次の非機能的なアプローチが使用されます。

    for value in collection:
      ...
  10. 安全な方法でのリソースの使用は、2つの言語間でかなり異なります。ここでの問題は、リソースを割り当て(ファイルを開く、データベースカーソルを取得するなど)、そのリソースに対して任意の操作を実行し、例外が発生した場合でも安全に閉じたいということです。

    Rubyでは、ブロックは非常に使いやすいため(#9を参照)、通常、このパターンは、リソースに対して任意の操作を実行するためのブロックを取得するメソッドとしてコーディングします。

    Pythonでは、名前付きの内部関数を作成する必要があるため(#9を参照)、任意のアクションの関数を渡すのは少し不格好です。代わりに、Pythonはwith安全なリソース処理のためにステートメントを使用します。Pythonオブジェクトを正しくクリーンアップする方法を参照してください詳細については。


2
3. Python 3はnonlocalこれを修正します。Pythonはジェネレーター式も提供します(リスト内包表記と同様ですが、要求されるまで何も計算しません-リスト内包表記は供給されたジェネレーター式と考えてくださいlist(イテラブルを取り、すべてを含むリストを返します)生成されるイテラブル)-これは、場合によっては多くの労力を節約できます)。

25
7.はい。val1 if expr else val2。8.ミックスインスタイルの拡張に主に使用されているようですが。

2
@ClintMillerおっと、スイッチ/ケースはありませんか?では、Pythonで同様の機能を実現するために推奨される方法は何ですか?if / else / if?
Phrogz、2011年

15
#4のルビの例は慣用的ではありません。書く方がルビっぽい(そして読みやすい)でしょうvalues.map{|v| v*v if v > 15}.compact。私見、これはあなたのpythonの例よりもさらに表現力があります(そして確かに明確です)。
sml 2011年

10
上記に加えて、!コンパクト関数のバージョンは、配列のコピーを回避します:values.map{|v| v*v if v > 15}.compact!。これは、入力リストと結果リストのみがメモリに存在することを意味します。ここ#4を参照してください:igvita.com/2008/07/08/6-optimization-tips-for-ruby-mri
sml

27

6年間のRubyを経て、Pythonを数か月間学びました。2つの言語の比較はそれほど優れていなかったので、自分で作成して自分で作成することにしました。今主に関数型プログラミングに関係していますが、Rubyのinject方法について言及しているので、同じ波長を使用していると思います。

これが役に立てば幸いです:Pythonの「醜さ」

正しい方向に移動するためのいくつかのポイント:

  • Rubyで使用する関数型プログラミングの優れた点はすべてPythonであり、さらに簡単です。たとえば、期待どおりに関数をマッピングできます。

    def f(x):
        return x + 1
    
    map(f, [1, 2, 3]) # => [2, 3, 4]
  • Pythonには、のように機能するメソッドがありませんeacheach副作用のみを使用するため、Pythonでの同等の機能はforループです。

    for n in [1, 2, 3]:
        print n
  • リスト内包表記は、a)関数とオブジェクトコレクションを一緒に処理する必要がある場合、およびb)複数のインデックスを使用して反復する必要がある場合に最適です。たとえば、文字列内のすべてのパリンドロームを検索するには(パリンドロームp()に対してtrueを返す関数があると想定)、必要なのは単一のリスト内包だけです。

    s = 'string-with-palindromes-like-abbalabba'
    l = len(s)
    [s[x:y] for x in range(l) for y in range(x,l+1) if p(s[x:y])]

3
ため息、私はその投稿を読んで、私の疑いを確認しました。Pythonの特別なメソッドの役割と有用性を理解している人はほとんどいません。それらは信じられないほど有用で標準化されており、頻繁に実装される組み込み関数との名前の競合を回避するために、そのように強調されています。Pythonを実際に知っている人は、その使用を思いとどまらせようとしているわけではありません。
Rafe Kettler

5
メソッドのしくみを理解していないようです。メソッドは、基本的に、最初の引数がメソッドが属するクラスのインスタンスである関数です。を記述するClass.method場合、メソッドは「バインドされていない」ため、最初の引数はClassインスタンスである必要があります。を記述するobject.methodと、メソッドはのobjectインスタンスに「バインド」されますClass。これにより、マップなどを使用して差分インスタンスのメソッドを毎回呼び出す(バインドされていないメソッドを渡す)か、インスタンスを固定して毎回異なる2番目の引数を渡すかを選択できます。どちらも便利です。
LaC、2011年

2
あなたが正しい、私は彼らがどのように機能するのか理解していませんでした。記事を公開して以来、私はそれについてより良い感覚を得ました。ありがとう!
David J.

10
[s[x:y] for x in range(l) for y in range(x,l+1) if p(s[x:y])]-この行は、Pythonの読み取りがいかに難しいかを示しています。Rubyのコードを読むときは、目を左から右に動かし、戻りません。しかし、Pythonコードを読み取るには、left-right-left-right-left-right ...とかっこ、かっこ、かっこ、かっこなどを使用する必要があります。また、Pythonでは、多くの場合、メソッドと関数を混在させる必要があります。それは狂気です:E(C(A.B()).D())Rubyの代わりにA.B.C.D.E
Nakilon '30年

2
@Nakilonこれが、ネストされたリスト内包表記を本当に単純なケースにのみ使用し、上記のようなものではない理由です。文字列内のすべての回文を検索するワンライナーを書くのは「賢い」かもしれませんが、コードゴルフ用に予約するのが最善です。他の誰かが後で読む必要がある実際のコードについては、数行の関数を書くだけです。つまり、その行は読みにくいですが、それは言語のせいではなく、プログラマのせいです。
Cam Jackson

10

私の提案:違いを学ぼうとしないでください。Pythonで問題に取り組む方法を学びます。それぞれの問題に対してRubyのアプローチ(言語の制限と長所をうまく機能させる)があるように、問題に対してはPythonのアプローチがあります。それらは両方とも異なります。各言語を最大限に活用するには、言語間の「翻訳」だけでなく、言語自体を学ぶ必要があります。

さて、そうは言っても、違いはより速く適応し、Pythonプログラムに1回限りの変更を加えるのに役立ちます。そして、それは執筆を始めるための良いことです。しかし、言語のセマンティクスの背後にある方法ではなく、なぜアーキテクチャと設計の決定の背後にあるのか、他のプロジェクトから学習してみてください...


7
私はあなたの提案に感謝します。私はこの感情(「慣習的なPythonのプログラミングを学ぶ」と解釈します)に完全に同意します。それがまさに私がやろうとしていることです。私は求めていないよ「RubyのためのPythonの名前は何each方法?」私が求めている「物事はルビーからPythonの異なる中で適切に行われてどのように、そしてどこが適切に同じことを行っていますか?」Python falseが実際にFalseである場合、Rubyesqueの方法でどこでいつ実行すべきか、どこでいつ実行すべきでないかを知ることは同じくらい重要です。
Phrogz、2011年

2
@Phrogz:それは公平です。私があなたの質問を解釈した方法は次のとおりでした:違いのリストを作成して、プログラミング言語を変更できるようにしましょう。しかし、それは公正な質問です。私はあなたが求めていたものを誤って解釈しただけだと思います。これは参照用にここに残しますが、他に何が起こるかを見るのは興味深いでしょう...
ircmaxell

私はpythonとrubyを同時に学んでおり、web app devには違いよりも類似点が多く見られます。
WesternGun、2017年

8

Rubyについてはほとんど知りませんが、あなたが言及したことについていくつかの箇条書きがあります。

  • nil、値がないことを示す値は次のようになりますNonex is Noneまたは-のように、またはブール値への強制によってx is not Noneではなく、==次の点を参照してください)。
  • None、ゼロ風の数字(00.00j(複素数))と、空のコレクションは([]{}set()、空の文字列""など)はfalsy、他のすべてが考慮されてtruthyと考えられています。
  • 副作用については、(for-)ループを明示的に指定します。副作用のない新しいものを生成するには、リスト内包表記(またはその関連-遅延1回限りの反復子のジェネレータ式、上記のコレクションのdict / set内包表記)を使用します。

ループについて:あなたはを持っていますfor、これはiterable(!no counting)で動作し、そしてwhile、あなたが期待することをします。イテレータに対する広範なサポートのおかげで、fromerははるかに強力です。リストの代わりにイテレーターになる可能性があるほぼすべてのものがイテレーターであるだけではありません(少なくともPython 3では、Python 2では両方があり、デフォルトはリストですが、残念ながら)。イテレータを操作するための多数のツールです- zip並列にイテレート可能オブジェクトの任意の数を反復し、enumerateあなたを与える(index, item)(上の任意さえabritary(おそらく大または無限)イテラブルをスライスし、だけではなく、リストの反復可能)!これらにより、多くのループタスクがはるかに簡単になることがわかりました。言うまでもなく、それらはリスト内包表記、ジェネレータ式などとうまく統合されます。


2
ジェネレータ式はクールです。それらはPythonにHaskellのような言語の遅延評価機能の少しを与えます。
クリントミラー、

@クリント:はい。そして、完全なジェネレーターは、より多くの機能を備えています(単純なケースでは必要ではありませんが、偶然に過半数が発生します)。

なぜx is Noneorでチェックするのx is not Noneですか?私はいつもに確認してくださいx == Nonex != None
John

@ジョン:ばかげた方法でx定義する__eq__と、誤検知が発生する可能性があります。が__eq__十分に注意深くプログラムされていない場合、AttributeError特定の値(つまりNone)が指定されると(たとえば)クラッシュする可能性があります。逆に、isオーバーライドすることはできません。常にオブジェクトの同一性を比較します。これは、シングルトンをチェックするための正しい(最も堅牢で、最も単純で、最もクリーンな)方法です。

1
@ジョン。「x is None」はそれを行うための絶対的な慣用的な方法です。python.net/~goodger/projects/pycon/2007/idiomatic/handout.html
tokland

6

Rubyでは、インスタンス変数とメソッドは、attr_accessorなどと明示的に関連付ける場合を除いて、まったく無関係です。

Pythonでは、メソッドは属性の特別なクラスであり、実行可能です。

だから例えば:

>>> class foo:
...     x = 5
...     def y(): pass
... 
>>> f = foo()
>>> type(f.x)
<type 'int'>
>>> type(f.y)
<type 'instancemethod'>

その違いは、たとえばfxの参照がメソッドオブジェクトを呼び出すのではなく、メソッドオブジェクトを参照するなど、多くの影響を及ぼします。また、ご覧のとおり、fxはデフォルトでパブリックですが、Rubyではインスタンス変数はデフォルトでプライベートです。


2
実際、私はそれをさらに明確に述べます。Pythonでは、メソッドは特定の種類の属性にすぎませんが、Rubyでは、属性は特定の種類のメソッドにすぎません。2つの言語間のいくつかの重要な対照的な機能は、Pythonのファーストクラス関数とRubyの統一アクセス原則
哲学
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.