59691


Pythonで以下のようなコードを書いてみて、一応正しく実行されたのですが  
改行やインデント、変数を含む文字列をexecする場合、このような書き方で良いのでしょうか。  
それとも、もっと良い書き方がありますでしょうか？

[code]

    test_str = ''
    for i in range(10):
        test_str += 'i = '+str(i) + '\n'
        test_str += 'if i%2==0:'+ '\n'
        test_str += '   if i%3==0:'+ '\n'
        test_str += '      print("'+str(i)+'")'+ '\n'
    exec(test_str)
    
[/code]

上記のコードは、0から9までの値をforループで回して  
2で割り切れる数かつ3で割り切れる数をprintするだけの内容です。  
if文にandを使っていないのは、2段階のif文でも問題なく動くか確かめるためです。


CC BY-SA 4.0
2019-10-13T03:11:41.280
59679
2019-10-14T13:21:50.217
2019-10-13T03:17:15.067
34471
34471
question
python
改行やインデントを含む文字列をexecする方法


string formattingを使えば、クオートを書く回数が減ります。  
<https://realpython.com/python-string-formatting/>

また、複数行にまたがる文字列を書く場合は、トリプルクオートを使うことが可能です。  
<https://docs.python.org/3/tutorial/introduction.html#strings>

[code]

    template = """
    i = {INDEX}
    if i%2==0:
        if i%3==0:
            print("{INDEX}")
    """
    
    test_str = ""
    for i in range(10):
        test_str += template.format(INDEX=i)
    
    exec(test_str)
    
[/code]


CC BY-SA 4.0
2019-10-13T23:29:57.400
59691
2019-10-13T23:29:57.400
59679
answer


[google python style
guide(日本語訳)](http://works.surgo.jp/translation/pyguide.html#id73)によると、

> ループ内の文字列を連結するために + や += 演算子を利用してはいけません。 文字列は イミュータブル
> であるため、これは不要なテンポラリーオブジェクトを作成し、実行時に線形制約クラスではなく 2 次制約クラスとなります。
> その代用として、各文字を配列に入れ、ループ終了後に ‘’.join で配列を連結します (もしくは cStringIO.StringIO
> バッファーへの追記):

なので以下を参考に書き直すとベターです。

[code]

    # No:
    test_str = ""
    for i in range(10):
        test_str += template.format(INDEX=i)
    
    # Yes:
    items = []
    for i in range(10):
        items += template.format(INDEX=i)
    test_str = ''.join(items)
    
[/code]

ループがそんなに多くないのならば、テンポラリーオブジェクトの影響が少なくなります。ループが多いまたは、文字列のコピーに時間がかかる場合、テンポラリーオブジェクトの生成は使用メモリと計算時間に悪い影響がでます。


CC BY-SA 4.0
2019-10-14T13:21:50.217
59702
2019-10-14T13:21:50.217
36129
59679
answer