Python > 言語 > 関数 > 変数のスコープ


Python - 言語 - 関数 - 変数のスコープ

*

*

変数のスコープ

局所(ローカル)変数

  • 局所(ローカル)変数
    • 関数の内部で定義された(代入された)変数
      • 同名の変数が,関数の外側で定義されていても構わない
        • 関数の外側の同名変数と,関数の内側の同名変数は,別々のスコープとなる
      • 外部に同名の変数があろうがなかろうが,関数内で変数に代入が起こった時点で,その変数はローカル変数となる
        • ローカル変数であれば,定義(最初の代入)が起こる前に使用されてはならない
  • 大域(グローバル)変数
    • 関数の外部で定義された(代入された)変数
      • 関数の中でグローバル変数を参照することはできる
        • 後述のglobal宣言をしなければ,関数の中で,代入することはできない
        • 後述のglobal宣言をすれば,関数の中での代入で,関数外に副作用を残すことができる

    関数globals()

    グローバル変数の一覧を含む名前辞書

    関数locals() 

    ローカル変数の一覧を含む名前辞書

局所変数と大域変数の共存

  • 関数の呼び出し前のメインでの値

    関数の実行終了時の関数内での値

    関数の呼び出し後のメインでの値

    大域変数

    x1, x2, x3, x4

    10, 20, 30, 40

    10, 20, 30, 40

    10, 20, 30, 40

    局所変数

    x1, x2

    100, 200

   1 # global_test_01.py 
   2 ## (大域変数と局所変数が使い分けられている例)
   3 ## (但し関数内では,大域変数は参照しても,代入はできない)
   4 
   5 def func():
   6     print( "---- 関数の中 (はじめ) -----" )
   7     x1 = 100                    # <------------ (f1) 局所変数x1の定義
   8     x2 = 200                    # <------------ (f2) 局所変数x1の定義
   9     print( "x1      = ", x1 )   # <------------ (f3) 局所変数x1が参照される
  10     print( "x2      = ", x2 )   # <------------ (f4) 局所変数x2が参照される
  11     print( "x3      = ", x3 )   # <------------ (f5) 大域変数x3が参照される
  12     print( "x4      = ", x4 )   # <------------ (f6) 大域変数x4が参照される
  13     print( "globals = ", globals() )
  14     print( "locals  = ", locals() )
  15     print( "---- 関数の中 (おわり) -----" )
  16 
  17 print( "---- メイン (関数呼び出し前) -----" )
  18 x1 = 10                         # <------------ (m1) 大域変数x1の定義
  19 x2 = 20                         # <------------ (m2) 大域変数x2の定義
  20 x3 = 30                         # <------------ (m3) 大域変数x3の定義
  21 x4 = 40                         # <------------ (m4) 大域変数x4の定義
  22 
  23 print( "x1      = ", x1 )       # <------------ (m5) 大域変数x1が参照される
  24 print( "x2      = ", x2 )       # <------------ (m6) 大域変数x2が参照される
  25 print( "x3      = ", x3 )       # <------------ (m7) 大域変数x3が参照される
  26 print( "x4      = ", x4 )       # <------------ (m8) 大域変数x4が参照される
  27 print( "globals = ", globals() )
  28 print( "locals  = ", locals() )
  29 # -------------------------------------------------------
  30 func()
  31 # -------------------------------------------------------
  32 print( "---- メイン (関数呼び出し後) -----" )
  33 print( "x1      = ", x1 )
  34 print( "x1      = ", x2 )
  35 print( "x1      = ", x3 )
  36 print( "x1      = ", x4 )
  37 print( "globals = ", globals() )
  38 print( "locals  = ", locals() )
  39 print( "---- メイン (おわり) -----" )

> python global_test_01.py
---- メイン (関数呼び出し前) -----
x1      =  10
x2      =  20
x3      =  30
x4      =  40
globals =  { ... (中略)... 'x1': 10, 'x2': 20, 'x3': 30, 'x4': 40}
locals  =  { ... (中略)... 'x1': 10, 'x2': 20, 'x3': 30, 'x4': 40}
---- 関数の中 (はじめ) -----
x1      =  100
x2      =  200
x3      =  30
x4      =  40
globals =  { ... (中略)... 'x1': 10, 'x2': 20, 'x3': 30, 'x4': 40}
locals  =  {'x2': 200, 'x1': 100}
---- 関数の中 (おわり) -----
---- メイン (関数呼び出し後) -----
10
20
30
40
globals =  { ... (中略)... 'x1': 10, 'x2': 20, 'x3': 30, 'x4': 40}
locals  =  { ... (中略)... 'x1': 10, 'x2': 20, 'x3': 30, 'x4': 40}
---- メイン (おわり) -----

局所変数と大域変数の共存できていない

  • 関数の中で先に代入せずに参照されてしまうと,その変数は,大域変数とみなされるので,局所変数として関数内で値を代入できない
    • 下記(f1)とf(3),(f2)とf(4)が,矛盾しているため

   1 # global_test_02.py 
   2 ## (実行時エラーが発生する例)
   3 ## (但し関数内では,大域変数は参照しても,代入はできない)
   4 
   5 def func():
   6     print( "---- 関数の中 (はじめ) -----" )
   7     print( "x1      = ", x1 )   # <------------ (f1) 大域変数x1が参照される
   8     print( "x2      = ", x2 )   # <------------ (f2) 大域変数x2が参照される
   9     x1 = 100                    # <------------ (f3) x1は既に大域変数として使用されているので,局所変数とできない
  10     x2 = 200                    # <------------ (f4) x2は既に大域変数として使用されているので,局所変数とできない
  11     print( "x3      = ", x3 )   # <------------ (f5) 大域変数x3が参照される
  12     print( "x4      = ", x4 )   # <------------ (f6) 大域変数x4が参照される
  13     print( "globals = ", globals() )
  14     print( "locals  = ", locals() )
  15     print( "---- 関数の中 (おわり) -----" )
  16 
  17 print( "---- メイン (関数呼び出し前) -----" )
  18 x1 = 10
  19 x2 = 20
  20 x3 = 30
  21 x4 = 40
  22 print( "x1      = ", x1 )
  23 print( "x2      = ", x2 )
  24 print( "x3      = ", x3 )
  25 print( "x4      = ", x4 )
  26 print( "globals = ", globals() )
  27 print( "locals  = ", locals() )
  28 # -------------------------------------------------------
  29 func()
  30 # -------------------------------------------------------
  31 print( "---- メイン (関数呼び出し後) -----" )
  32 print( "x1      = ", x1 )
  33 print( "x2      = ", x2 )
  34 print( "x3      = ", x3 )
  35 print( "x4      = ", x4 )
  36 print( "globals = ", globals() )
  37 print( "locals  = ", locals() )
  38 print( "---- メイン (おわり) -----" )

>python global_test_02.py
---- メイン (関数呼び出し前) -----
x1      =  10
x2      =  20
x3      =  30
x4      =  40
globals =  { ... (中略)...'x1': 10, 'x2': 20, 'x3': 30, 'x4': 40}
locals  =  { ... (中略)...'x1': 10, 'x2': 20, 'x3': 30, 'x4': 40}
---- 関数の中 (はじめ) -----
Traceback (most recent call last):
  File "global_test_02.py", line 29, in <module>
    func()
  File "global_test_02.py", line 7, in func
    print( "x1      = ", x1 )   # <------------ (f1) 大域変数x1が参照される
UnboundLocalError: local variable 'x1' referenced before assignment

大域(グローバル)変数

  • 大域(グローバル)変数
    • 関数の外部で定義された(代入された)変数
      • 関数の中でグローバル変数を参照することはできる

大域(グローバル)変数への代入(global宣言)

  • 大域(グローバル)変数への代入
    • 関数の外部で定義された変数
      • 関数の中でグローバル変数を参照することはできる
      • global宣言すれば,関数の中で,代入することができる

例: global宣言を行った例

  • 関数の呼び出し前のメインでの値

    関数の実行終了時の関数内での値

    関数の呼び出し後のメインでの値

    大域変数

    x1, x2, x3, x4

    10, 20, 30, 40

    100, 200, 30, 40

    10, 20, 30, 40

    局所変数

    x1, x2

   1 # global_test_03.py 
   2 ## (global宣言する例)
   3 
   4 def func():
   5     print( "---- 関数の中 (はじめ) -----" )
   6     global x1, x2               # <------------ (f0) global宣言: 変数x1とx2は大域変数
   7     print( "x1      = ", x1 )   # <------------ (f1) 大域変数x1が参照される
   8     print( "x2      = ", x2 )   # <------------ (f2) 大域変数x2が参照される
   9     x1 = 100                    # <------------ (f3) x1は既に大域変数として使用されているので,局所変数とできない
  10     x2 = 200                    # <------------ (f4) x2は既に大域変数として使用されているので,局所変数とできない
  11     print( "x3      = ", x3 )   # <------------ (f5) 大域変数x3が参照される
  12     print( "x4      = ", x4 )   # <------------ (f6) 大域変数x4が参照される
  13     print( "globals = ", globals() )
  14     print( "locals  = ", locals() )
  15     print( "---- 関数の中 (おわり) -----" )
  16 
  17 print( "---- メイン (関数呼び出し前) -----" )
  18 x1 = 10
  19 x2 = 20
  20 x3 = 30
  21 x4 = 40
  22 print( "x1      = ", x1 )
  23 print( "x2      = ", x2 )
  24 print( "x3      = ", x3 )
  25 print( "x4      = ", x4 )
  26 print( "globals = ", globals() )
  27 print( "locals  = ", locals() )
  28 # -------------------------------------------------------
  29 func()
  30 # -------------------------------------------------------
  31 print( "---- メイン (関数呼び出し後) -----" )
  32 print( "x1      = ", x1 )
  33 print( "x2      = ", x2 )
  34 print( "x3      = ", x3 )
  35 print( "x4      = ", x4 )
  36 print( "globals = ", globals() )
  37 print( "locals  = ", locals() )
  38 print( "---- メイン (おわり) -----" )

>python global_test_03.py
---- メイン (関数呼び出し前) -----
x1      =  10
x2      =  20
x3      =  30
x4      =  40
globals =  { ... (中略)...'x1': 10, 'x2': 20, 'x3': 30, 'x4': 40}
locals  =  { ... (中略)...'x1': 10, 'x2': 20, 'x3': 30, 'x4': 40}
---- 関数の中 (はじめ) -----
x1      =  10
x2      =  20
x3      =  30
x4      =  40
globals =  { ... (中略)...'x1': 100, 'x2': 200, 'x3': 30, 'x4': 40}
locals  =  {}
---- 関数の中 (おわり) -----
---- メイン (関数呼び出し後) -----
x1      =  100
x2      =  200
x3      =  30
x4      =  40
globals =  { ... (中略)...'x1': 100, 'x2': 200, 'x3': 30, 'x4': 40}
locals  =  { ... (中略)...'x1': 100, 'x2': 200, 'x3': 30, 'x4': 40}
---- メイン (おわり) -----
*

リファレンス

*



Software Engineering(IIJIMA, Tadashi -- Keio Univ.)



*

SoftEng: Python/Lang/Function/Scope (last edited 2018-09-28 15:10:19 by TadashiIijima)