[ 参照リンク:Pythonの名前空間とスコープ](https://www.imangodoc.com/106.html)
目次
exec()は簡単に使用できます
単純な文字列コードを動的に実行する
より複雑なコードを動的に実行する
ファイル内のPythonコードを実行します
execでパラメータを渡す
使用中に発生した問題
参照
exec()は簡単に使用できます
個人的には、Pythonでexec()を使用して、文字列コードを動的に実行することを好みます。forループでは、list1 = 1、list2 = 2、list3 = 3 ...などの多数のステートメントをすばやく実行して、コードを表示できます。より簡潔に。
まず、exec()について簡単に説明します。exec()は非常に興味深く実用的な組み込み関数です。数式の結果を計算する機能しか実行できないeval()とは異なり、exec()は複雑なPythonを動的に実行できます。コードは強力ですが、踏みやすい小さな場所がたくさんあります。ピットは良いですが、理解しにくいです。光と影が共存しています。
単純な文字列コードを動的に実行する
より複雑なコードを動的に実行する
func = "def fact(n):\n\treturn 1 if n==1 else n*fact(n-1)"
exec(func)
a = fact(5)
print(a)
ファイル内のPythonコードを実行します
eg.txtに入れたいPythonコードを保存します
def fact(n):
if n==1:
return 1
else:
return n*fact(n-1)
t = fact(6)
print(t)
execでパラメータを渡す
x = 10
expr = """
z = 30
sum = x + y + z
print(sum)
"""
def func():
y = 20
exec(expr)
exec(expr, {'x': 1, 'y': 2})
exec(expr, {'x': 1, 'y': 2}, {'y': 3, 'z': 4})
func()
使用中に発生した問題
今日それを使用しているときにいくつかの問題に遭遇し、単にそれを記録します。
def main():
file_list = [2014, 2045, 2065, 2070, 2080, 2110, 2123, 2133]
generate_outliers_analysis_log(file_list, "log/outliers.log")
for file in file_list:
csv_df = csv_file_to_df(r"D:/FTPD/newEnv/" + str(file) + ".csv")
port_suffix = [33, 35, 36, 37, 39, 40]
loc = locals()
for suffix in port_suffix:
#文字列コードを実行して、同じステートメントを繰り返し実行しないようにします
exec("sorted_df_%s = get_sorted_port_df(csv_df, '25GE1/0/%s')" % (str(suffix), str(suffix)))
sorted_df_33, sorted_df_35, sorted_df_36 = loc["sorted_df_33"], loc["sorted_df_35"], loc["sorted_df_36"]
sorted_df_37, sorted_df_39, sorted_df_40 = loc["sorted_df_37"], loc["sorted_df_39"], loc["sorted_df_40"]
sorted_df_list = [sorted_df_33, sorted_df_35, sorted_df_36, sorted_df_37, sorted_df_39, sorted_df_40]
name_list = ["25GE1/0/33", "25GE1/0/35", "25GE1/0/36", "25GE1/0/37", "25GE1/0/39", "25GE1/0/40"]
save_port_figure_and_excel(range(1, 7), sorted_df_list, name_list, str(file), 'port_csv/' + str(file) + '.xlsx')
次のコード行は、実行中にエラーが発生しました。
sorted_df_33, sorted_df_35, sorted_df_36 = loc["sorted_df_33"], loc["sorted_df_35"], loc["sorted_df_36"]
エラーメッセージは次のとおりです。
sorted_df_33, sorted_df_35, sorted_df_36 = loc["sorted_df_33"], loc["sorted_df_35"], loc["sorted_df_36"]KeyError: 'sorted_df_33'。
一見奇妙です。KeyErrorの問題を回避するために、execはlocals()と組み合わせて使用されることがよくあります。
まず、地元の人に関しては、注目に値する4つのポイントがあると思います。
ポイント4の意味、簡単な例を挙げてください
def test():
a = 13
loc = locals()
exec('b = a + 1')
b = loc['b']
print(b)
上記の小さなコードでは、行loc = locals()が実行されると、locディクショナリには「loc」のキーがあります。これは、locディクショナリ自体のキーと値のペアです。
そして、このlocは循環参照です。以下のデバッグ図を見てください。 locals()には、現在のローカルスコープ内のすべてのローカル変数が含まれるためです。 loc自体もローカル変数であるため、循環参照を作成します。
幹部の一般的な落とし穴
https://segmentfault.com/a/1190000019217209
発生した問題の分析
上記のリンク先の記事を読んだ後、私は個人的に説明が非常に徹底的であると感じています。簡単に振り返ってみましょう。つまり、次の例1では、KeyErrorが報告され、次の例2では、エラーは報告されません。これは、locals()の呼び出し場所に関連しています。Locals()は、ローカル変数のディクショナリのコピーです。実行時のローカルネームスペース(ローカル変数ディクショナリ)は変更できないため、exec()関数での変数の割り当ては正しくありません。影響はありますが、locals()ディクショナリは可変であり、exec()関数の影響を受けます。つまり、後でexecで動的に実行される値を取得して新しい変数に割り当てる場合は、execの前にlocals()を呼び出す必要があります。そうしないと、取得できません。
さて、これに基づいて、今日発生した問題を確認しましょう。まず、上記の問題があるビジネスコードを簡略化して、以下の例3のexec + locals + placeholder example3を使用し、次にexample4のメソッドを使用して単純にします。検証。ねえ、ここに興味深い問題があります。論理的に言えば、example3()関数では、2行目がlocを定義します。ここのlocは、3行目と4行目の実行が完了した後にexecによって変更されます。 locには、「a0」、「a1」、「a2」、「a3」、「a4」の5つのキーが必要です。これはexample4でも確認されています。つまり、元の変数名を使用しない限り取得できます。このようなエラーが発生する理由がよくわかりません。これは、execとプレースホルダーの設計上の問題である可能性があります。これから、結論を導き出すこともできます。コードで動的に実行されるexecの変数値を取得するには、再実行しないことをお勧めします。名前を付けて、これらの小さくて些細な問題を見つけないようにして、より多くの時間を費やしてください。 :
参照
https://segmentfault.com/a/1190000014581721
https://segmentfault.com/a/1190000019217209
https://python3-cookbook.readthedocs.io/zh_CN/latest/c09/p23_executing_code_with_local_side_effects.html
Recommended Posts