2017-07-25 10 views
1

データ処理タスクを行うとき、私はしばしば、ある入力反復可能なデータに一連のコンポジション、ベクトル化関数などを適用して最終結果を生成します。理想的には、リストとジェネレータの両方で動作するもの(他のイテラブルに加えて)が必要です。私はこれを達成するためにコードを構造化するための多くのアプローチを考えることができますが、私が考えることができるあらゆる方法は、私に汚れている/ unidiomaticと感じる1つ以上の方法があります。私はこれを行うために考えることができるさまざまな方法を以下に概説しましたが、私の質問はです。これを行うには、推薦的で慣用的な方法がありますか?一般の代表である簡単な例を示す私は考えることができるイテラブルに連続ステップを適用するためのPythonイディオム

方法、:

これは、すべての非のために読み取ることがしばしば非常に困難である一つの大きな表現として

result = [sum(group) 
      for key, group in itertools.groupby(
       filter(lambda x: x <= 2, [x **2 for x in input]), 
       keyfunc=lambda x: x % 3)] 

それを書きます簡単な一連のステップ。コードを読み取ると、逆の順序で各ステップが発生します。

保存が各段階別の変数名に

squared = [x**2 for x in input] 
filtered = filter(lambda x: x < 2, squared) 
grouped = itertools.groupby(filtered, keyfunc=lambda x: x % 3) 
result = [sum(group) for key, group in grouped] 

これは、多くの場合、記述的に名前を付けるために難しいことができますローカル変数の数を紹介。さらに、中間ステップのいくつかまたはすべての結果が特に大きい場合には、メモリを非常に無駄にする可能性があります。このプロセスにステップを追加する場合は、すべての変数名が正しく更新されるように注意する必要があります。たとえば、すべての数値を2つに分割する場合は、行番号halved = [x/2.0 for x in filtered]を追加しますが、変更する必要があります次の行にfilteredhalvedとなります。

ストア同じ変数名に各ステップ

tmp = [x**2 for x in input] 
tmp = filter(lambda x: x < 2, tmp) 
tmp = itertools.groupby(tmp, keyfunc=lambda x: x % 3) 
result = [sum(group) for key, group in tmp] 

私は、これは、これらのオプションの最小悪いように私には思われると思いますが、一般的に名前のプレースホルダ変数で物事を格納することは私には非Python的に感じているとそこにはよりよい道があると私に思わせます。

+0

これは主に意見と好みのスタイルの問題です。他のスタイルもあります。より自然なカスケードを可能にする['fluent interface'](https://en.wikipedia.org/wiki/Fluent_interface)または[' method chaining'](https://en.wikipedia.org/wiki/Method_chaining)通話の – AChampion

答えて

1

コードレビューは、よくスタイルの質問のためのより良い場所です。 SOは問題解決のためにより多くのことです。しかし、この例の完成度については、CRが嫌なことがあります。

しかし、私はいくつかの観察することができます

  • あなたが関数内でこの計算をラップする場合、命名は、このような大したことではありません。名前は全体的に意味がある必要はありません。

  • あなたの数式はジェネレータです。 Itertoolsはジェネレータやジェネレータを生成する傾向があります。表現。だからメモリの使用はあまり問題にならないはずです。 def機能代わりのラムダを使用


def better_name(input): 
    squared = (x**2 for x in input) # gen expression 
    filtered = filter(lambda x: x < 2, squared) 
    grouped = itertools.groupby(filtered, lambda x: x % 3) 
    result = (sum(group) for key, group in grouped) 
    return result 

list(better_name(input)) 

、コードをより明確にすることができます。トレードオフがあります。あなたのラムダは、私がおそらくそれらを守るほど簡単です。

第2のオプションは、第1のオプションよりもはるかに読みやすいです。表現の順序は私の読書と精神的評価を導く。1位では、最も内側または最初の評価を特定することは難しいです。 groupbyは複雑な操作なので、アクションを区画化するのに役立ちます。 filterドキュメントに続き


、これらは等価です。

filtered = filter(lambda x: x < 2, squared) 
filtered = (x for x in squared if x<2) 

私はreturnがありませんでした。この関数は、私が示すようにジェネレータを返すことも、評価されたリストを返すこともできます。

groupbykeyfuncはキーワード引数ではなく、むしろ位置的なものです。

groupbyは複雑な関数です。タプルを生成するジェネレータを返します。タプルはジェネレータそのものです。これを返すことで、より明白になります。

((key, list(group)) for key, group in grouped) 

したがって、その使用法を明確にするコードスタイルが望ましいです。

関連する問題