2009-06-09 7 views
4

私は次のリストの内包表記を使用しています:キャッシュ値

resources = [obj.get("file") for obj in iterator if obj.get("file") != None] 

はそれがないように、それはif文でチェックだときobj.get("file")の値を「キャッシュ」する方法はあります返信リストを生成するときにobhに対してgetを再度呼び出す必要がありますか?

答えて

6

あなたの代わりにあなたは、単に使用することができますfilter使用して一覧/イテレータの内包表記で滞在したい場合:

resources = [file_obj 
      for file_obj in (obj.get("file") for obj in iterator) 
      if file_obj is not None] 
+0

ありがとう、これは私が探していた一般的な解決策です。 – Kai

9
resources = filter(None, (obj.get("file") for obj in iterator)) 

独自の評価機能を提供する方法については、filterのドキュメントを参照してください。上記のように関数にNoneを渡すと、真ではないすべての値が除外されます。

obj.get()が奇妙な__nonzero__メソッドを持つオブジェクトを返す場合、元のコードとまったく同じ結果を得るにはlambda obj: obj != Noneを渡す必要があります。

+0

「奇妙な__nonzero__持つオブジェクト」 - int型、またはstrのように。 –

1

はこのような何かを試してみてください:

resources = filter(lambda x: x is not None, [obj.get("file") for ob jin iterator]) 
+0

フィルターにラムダ関数は必要ありません。 Noneを渡すことで、デフォルトで恒等関数になります(falseに評価されるオブジェクトは除外されます)。 http://docs.python.org/library/functions.html#filter – tgray

+0

2番目の考えでは、イテラブルに他の「偽の」要素(0など)がある場合、ラムダが必要な場合があります。 – tgray

+0

Hmm。もし私がそれを必要としなくても、私はラムダの証言を好きです。 – SingleNegationElimination

1

値を保持するために、一時的な辞書を作成します。その後、キャッシュとしてこの辞書を使用する関数を作成し、そのように、リスト内包でその機能を使用します。

obj_cache = {} 

def cache_get (target, key): 
    if (target, key) not in obj_cache: obj_cache[(target, key)] = target.get(key) 
    return obj_cache[(target, key)] 

resources = [cache_get(obj, "file") for obj in iterator if cache_get(obj, "file") != None] 

はまた、あなたはおそらく既にこれを知っている(そうであれば、この答えを無視してください)、 obj.get( "file")がデータベース呼び出しを行ったり、ファイルを開いたり、ネットワークを介して要求したり、高価なものを実行したりしない限り、1回ではなく2回繰り返すことはおそらく無害です。あなたのコストにO(n)を加えるだけです。

関連する問題