2017-08-20 3 views
1

exec()内から関数が出力されても、その関数に必要なすべてのパラメータを渡します。私はここに似たようなケースチェックした関数内でリスト内包の中にネストされたループを入れたexec()関数

def list_filter(expr,datalist,includelist) : 
    exec(expr) 
    print outlist 


datalist=['try to kill me','black image'] 
includelist=['me'] 
expr="outlist = [i for i in datalist if all(j in i for j in includelist) ]" 
exec(expr) 
print outlist 
list_filter(expr,datalist,includelist) 

How does exec work with locals?

しかしこれは、私はバージョン2.7.13を使用している別のエラーが、あると私は一般的な条件の下でチェックし、正常にexec()このコードを考えてみましょうまったくエラーはありません。私は、リスト内包表記の中に「入れ子にされたループ」がある場合、all()any()のように、この問題が現れることがわかりました。この場合のように、リスト内包(expr = "outlist = [i for i in datalist ]"にする)からif conditionを削除すると、いつものように正しい出力が得られます。

理由は何ですか?

+2

あなたが解決しようとしている全体的な問題は何ですか?私はexecが正しいことを疑う。 –

+0

'all(...)'内部のジェネレータ表現が一種の関数呼び出しに内部的にコンパイルされ、 'exec'と組み合わされたときに問題を引き起こすと思われるので、ここでは何か変わったことがあります。リストの理解を代わりに使用すると、期待通りに動作します: 'all([j in i for j for includelist])'。つまり、おそらく本当に 'exec'を使うべきではないでしょう。 –

+0

@AlexHall:たとえば、exprの内部を修正したいと思います。** expr = "outlist = [リスト内のi__strip____case__]" **。だから** expr = expr.replace( '__ strip __'、 '。stripmode else' ')**または** expr = expr.replace(' __ case __ '、'。lower)の場合は、lstrip()。 () ''ではない場合は '')**)**。これらの2つの変更例(strip()とlower())は、実際には行列形式のパラメータが発生します。通常のif -then構造体を使用するのではなく、文字列置換メソッドを使用しようとします。このように私は簡単に文字列として式を変更することができます。 – andio

答えて

0

ほとんどの場合、execを使用することはほとんどお勧めできません。この場合は、まったく使用しないでください。

しかし、あなたが尋ねたので、私はexecのスコープルールに精通していないが、私は多くの場合、あなたがする必要があることがわかっ

def list_filter(expr, datalist, includelist): 
    exec(expr, locals()) 
    print outlist 

:あなたはローカルスコープから変数を渡す場合、それが正常に動作します変数を明示的に渡します(特にexecがグローバルスコープにない場合)。

def list_filter(expr, datalist, includelist): 
    exec(expr, {'datalist': datalist, 'includelist': includelist}) 
    print outlist 

それはも、あなたはexecにスコープから変数を渡す必要がありdocumentationに述べています:あなたも、明示的にそれらを渡すことができ、あなたの場合は

建て-in関数globals()locals()はそれぞれ、現在のグローバル辞書とローカル辞書を返します。これは、execが使用するために渡すのに便利です。

関連する問題