web-dev-qa-db-ja.com

学習Python Rubyから;相違点と類似点

私はRubyをよく知っています。現在、Pythonを学ぶ必要があると思います。両方を知っている人にとって、2つのコンセプトは似ており、違いは何ですか?

Learning Lua for JavaScripters :空白の重要性やループ構造などの簡単なもの。 Pythonのnilの名前、および「真」と見なされる値。 mapおよびeachと同等のものを使用するのが慣用的か、またはmumblesomethingaboutlistcomprehensionsmumble規範?

さまざまな回答が得られたら、それらをコミュニティwikiに集約して喜んでいます。それ以外の場合は、すべての人が互いに戦い、ベビーベッドをして、真の包括的なリストを作成することができます。

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

128
Phrogz

私との主な違いは次のとおりです。

  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コードはコンパクトではありません。また、values配列を最初に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コードは通常、より機能的なスタイルで記述されますthan Python code。たとえば、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オブジェクトを正しくクリーンアップするにはどうすればよいですか? 詳細については。

151
Clint Miller

Rubyを6年間使った後、2か月間、Pythonを学びました。2つの言語の比較はあまりありませんでした。さて、これは主に関数型プログラミングに関係するですが、Rubyのinjectメソッドに言及しているので、私たちは同じ波長にいると思います。

これが役立つことを願っています: The Pythonの「ugさ」

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

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

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

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

    _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])]
    _
27
David J.

私の提案:違いを学ぼうとしないでください。 Pythonで問題に取り組む方法を学びます。各問題へのRubyアプローチ(言語の制限と強みを非常にうまく機能させる)があるように)、Python問題へのアプローチ。各言語を最大限に活用するには、一方から他方への「翻訳」だけでなく、言語自体を実際に学習する必要があります。

さて、それで、違いはあなたがより速く適応するのに役立ち、Pythonプログラムに1つの変更を加えます。そしてそれは執筆を始めるためにそれで問題ありません。しかし、他のプロジェクトから学びましょう言語のセマンティクスの背後にあるのではなく、アーキテクチャと設計の決定の背後にある理由...

10
ircmaxell

私は少しRubyを知っていますが、あなたが言及したことに関するいくつかの箇条書きがあります:

  • nil(値がないことを示す値)はNoneになります(_x is None_ではなく、_x is not None_または_==_のようにチェックすることに注意してください) -またはブール値への強制により、次のポイントを参照)。
  • None、ゼロのような数字(_0_、_0.0_、_0j_(複素数))および空のコレクション(_[]_、_{}_、 set()、空の文字列_""_など)は偽と見なされ、他のすべては真実と見なされます。
  • 副作用の場合、(for-)明示的にループします。副作用のない新しいものを生成するには、リスト内包表記(またはそれらの親類-怠oneな1回限りの反復子のジェネレータ式、上記コレクションの辞書/セット内包表記)を使用します。

ループについて:forは反復可能(!カウントなし)で動作し、whileは期待どおりに動作します。 fromerは、イテレーターの広範なサポートのおかげで、はるかに強力です。リストの代わりにイテレータになり得るほぼすべてがイテレータであるだけではありません(少なくともPython 3-in Python 2、あなたは両方を持っていて、悲しいことにデフォルトはリストです。イテレータを操作するための多数のツールがあります-Zipは任意の数の反復可能要素を並列に反復し、enumerateは_(index, item)_(onany反復可能(リスト上だけでなく)、さらには(大規模または無限の)反復可能イテレートをスライスします!これらの多くのループタスクがはるかに簡単になることがわかりました。リスト内包表記、ジェネレータ式などとうまく統合されます。

8
user395760

Rubyでは、インスタンス変数とインスタンスは完全に無関係です。ただし、それらをattr_accessorまたはそのようなものと明示的に関連付ける場合を除きます。

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

たとえば、次のとおりです。

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

この違いは、たとえばf.xを参照することでメソッドオブジェクトを呼び出すのではなく、メソッドオブジェクトを参照するなど、多くの意味を持ちます。また、ご覧のとおり、f.xはデフォルトでパブリックですが、Rubyでは、インスタンス変数はデフォルトでプライベートです。

6
Paul Prescod