53927


Pythonでプログラムが長くなったので実行部分と関数やデータ部分に分けようと思い、listing.pyというファイルに

[code]

    def alist():
        list1=[hogehoge]
    
[/code]

とデータを並べ、それをmain.pyで

[code]

    import listing
    listing.alist()
    
[/code]

としましたが、エラー

[code]

    NameError: name 'list1' is not defined
    
[/code]

となり、list1に代入されません。  
defの中でglobal list1とやってもだめでした。

どのように対処すべきでしょうか。  
どうぞよろしくお願いいたします。


CC BY-SA 4.0
2018-12-20T18:01:27.647
51403
2019-04-05T00:53:24.940
2018-12-21T14:29:00.717
12457
12457
question
python
Pythonで自作モジュールをimportする


回答末尾のサンプルコードの項番1.と3.でエラーが発生します。  
おそらく項番1.のようなコードを実行してエラーになっているのではないでしょうか。

簡単に解説しますと、[import したモジュールの global
変数にアクセスする方法](https://qiita.com/sutoh/items/bce50207d1f05e6a52df)のようにpythonのグローバル変数は完全にグローバルではありません。  
importしたモジュール内で宣言された変数にアクセスする場合は、`{モジュール名}.{変数名}`でアクセスする必要があります。(項番2.)

もしくは関数の戻り値を`return`で返して変数に渡すのが正当な解決方法です。(項番4.)  
変数のスコープはけっこうハマりやすい罠になります。私も回答のために調べてみて勉強になりました。

下記のサンプルコードはpython 3.xのみで動作します。  
また、`listing.py`が既に存在する場合、上書きします。  
ご承知おきください。

[code]

    with open('listing.py', 'w', encoding='utf-8') as f:
        f.write("""# -*- coding: utf-8 -*-
    def alist():
        global list1
        list1 = [ 'hoge', 'fuga', 'piyo' ]
    
    def blist():
        global list2
        list2 = [ 'foo', 'bar', 'baz' ]
        return list2
    """)
    
    import sys
    import listing
    
    listing.alist()
    # 1. importしたモジュール内変数には直接アクセスできない
    try:
        print(list1)
    except NameError as e:
        print(e.with_traceback(sys.exc_info()[2]))
    # 2. モジュール内変数としてglobalにアクセスできる
    print(listing.list1)
    
    # 3. 戻り値を受け取らないので動かない
    listing.blist()
    # 4. 戻り値を受け取るので動く(コメントアウトしてエラーを誘発中)
    #list2 = listing.blist()
    
    try:
        print(list2)
    except NameError as e:
        print(e.with_traceback(sys.exc_info()[2]))
    
[/code]


CC BY-SA 4.0
2019-04-05T00:53:24.940
53927
2019-04-05T00:53:24.940
9820
51403
answer