オブジェクトのリストがありcheese
ます。Cheese
と呼ばれる、db などを使って一連の処理を行うメソッドがありout_of_stock()
ます。
そう:
[cheese.out_of_stock() for cheese in cheeses]
ずさんな感じです。一連の副作用(在庫をゼロにする)のために何かをしている(リストを作成している)ように。
私は愚かですか?これは方法に主観的ですか?
リスト内包表記は、リストを作成するためのものです。それはあなたがここでやっていることではないので、私はそれを避けます.
個人的には、私はそうするだろう
for cheese in cheeses:
cheese.out_of_stock()
これは私にはもう少し明白に感じます。これは別の行ですが、そのコードを読んでいる別のプログラマーはそれをよく理解できると思いますが、リスト内包版は少し混乱するかもしれません。さらに、後で他の誰かがやってきて (それがout_of_stock
値を返さないことを知らずに)、後でそのリストを使用しようとするかもしれないと想像できます。
とはいえ、何も問題はないと思います。最終的には、後で誰がそのコードを読むか (自分自身か他の人か) と、彼らが何が起こっているかを知るかどうかにかかっています。
編集: また、Haskell から取得した素敵な関数型プログラミング構造を使用して、厄介なステートフルなことを行っています...
意味的には、cheese.out_of_stock がブール値を返せば問題ありません。ただし、cheese.out_of_stock が値を返さない場合、これはあまりお勧めできません。非常に混乱を招き、保守が困難になります。
import this
詳細については
あなたがこれの戻り値で何かをしているなら、cheese.out_of_stock()
これは完全にPythonicです。リスト内包表記の結果を破棄する場合、それは悪いスタイルです。
リストの作成は時間とメモリの無駄です。ピーターの答えfor
から2行のループを使用するだけです。
リスト内包表記は通常、フィルタリング (または、内包表記の結果が後で使用される同様のもの) に使用されますが、反復データでメソッドを呼び出すループを置き換えるためには使用されません。したがって、これは機能しますが、醜いロックになります。
答えは、リストが必要かどうかに完全にかかっています。リスト内包表記は、多くの場合、次のようなループの適切な代替になります。
stock = []
for cheese in cheeses:
stock.append(cheese.out_of_stock())
ただし、次のようなループはめったにありません。
for cheese in cheeses:
cheese.out_of_stock()
人々がリスト内包表記を読むとき、プログラムの意味に影響を与えないキャッシングのようなものや、もちろんリストの構築を除けば、通常、副作用があるとは思っていません。確かに、それが持つ副作用は、プログラムの正確さには必要ありません。これは、コマンドとクエリの分離なしで API を使用している場合、最初のタイプのループでは回避する価値があることも意味します。リストが必要ですが、依存する副作用もある場合は、理解ではなくループの使用を検討する必要があります.out_of_stock()
。
それは醜いです、それをしないでください。
見苦しくない、非常によく似た方法があります。次のような事前定義された関数が必要です。
def consume(iter):
for i in iter:
pass
これで、次のようなコードを記述できます。
consume(cheese.out_of_stock() for cheese in cheeses)
本当に、これはジェネレーター式で呼び出される関数にラップされたピーターの提案にすぎません。リスト内包表記よりははるかに優れていますが、それでも完全に美しいとは言えません。for ループを直接使用するのが本当に最善 (最も明示的) です。
for cheese in cheeses: cheese.out_of_stock()
まだワンライナーであり、不要なリストを作成するという副作用を回避します。