言い換えれば、Pythonデザインに関連する理由はありますか?
_map, filter, reduce
_などの関数は単純な関数です。
それは単に悪いデザインの選択ですか(それが良いものである場合は、説明してください)?たとえばscalaでは、smth.map(func1).reduce(func2)
のようなコレクションメソッドをチェーンできます。それは私にとってはるかに便利なようです。
これらのメソッドをどのクラスに配置しますか?
Pythonでは、リスト、タプル、辞書、ファイル、文字列、セット、配列などでmap
を使用できます。map
、reduce
、filter
などを配置するコレクション基本クラスはありません。
さて、pythonは、これらすべてのさまざまなものが継承されたコレクションクラスを持っている可能性があります。しかし、それは実際にはpythonの「精神」に反することになります。In pythonすべてがダックタイピングされています。適切なメソッドがあるため、機能します。___iter__
_を定義するものには、map
、reduce
、およびfilter
を使用できます。コレクションクラスをサブクラス化する必要があると、それに反します。
現状では、map/reduce/filterはPythonicソリューションとは見なされていません。
map(x, lambda y: y+1)
の代わりに_[y + 1 for y in x]
_を使用してください
filter(x, lambda y: y % 2 == 0)
の代わりに_[y for y in x if y % 2 == 0]
_を使用してください
reduce(x, lambda x,y: x+y)
の代わりに
_sum = 0
for y in x:
sum += y
_
これは単なる歴史的遺物だと思います。これらの機能は、流体インターフェースが大流行していなかったかなり前に導入されました。それ以来、誰もが彼らに慣れました。 (そうです、あなたはそれを「悪いデザイン」と書くことができます)。
これらの関数をリストに後付けすることはできますか?おそらく、そうではなかったはずです。
最初、 There should be one-- and preferably only one --obvious way to do it.
次に、そして最も重要なこととして、map
、reduce
および他の多くの関数は、リストだけでなく、anythingでも機能します。反復可能。タプル、セット、dict、そして最も重要なこととして、反復を実装するユーザー定義クラス(__iter__
)またはジェネレーター(yield
を使用)。
したがって、すべてのイテラブルまたはジェネレーターは、何らかの形でmap
、reduce
の独自の実装、およびイテラブル/ジェネレーターを受け入れて互換性のあるものを返す他の関数の束を受け取る必要があります。これには、map
やreduce
のような名前を公開しないように反復可能なexistingクラスが必要になります。コード破壊的な変更は、Pythonメンテナとコミュニティの両方から非常に嫌われています。
代わりに、追加のインターフェイスを提供する独自のクラスに物事をラップして、言及した流動的なスタイル、 パイプスタイル 、またはその他のものを楽しむことができます。
質問の2番目の部分に関するいくつかの考慮事項:
それは単に悪いデザインの選択ですか(それが良いものである場合は、説明してください)?たとえば、scalaでは、smth.map(func1).reduce(func2)のようなコレクションメソッドをチェーンできます。それは私にとってはるかに便利なようです。
デザインが悪いとは思いません:Pythonは手続き型とオブジェクト指向の両方のスタイルをサポートしており、コレクションの高階関数には2つのスタイルのいずれかを選択する必要がありました。RubyおよびScalaはオブジェクト指向スタイルを支持しているため、高次の方法を選択しました。
メソッドチェーンの利便性に関しては、カリー化をサポートする言語で対応するコンパクトな構文があります。 Haskellではあなたは書くことができます
(map func1 . filter func2) smthg
おそらく、標準関数ではない場合でも、Python(たとえば、 PyMonad を参照)で同様のことを行うことができます。