Pythonの勉強するよ【関数編②】
どもども。今回は予定通り更新することができました。
前回は、ついに関数について勉強を始めました。
【前回の復習】
・関数とは、小さなプログラムの集まりのこと。
・パラメータなし関数の定義の仕方
def 関数名():
処理内容
・パラメータありの関数の定義の仕方
def 関数名( param ):
処理内容
・戻り値とは、関数が返す実行結果のこと。
・戻り値は、関数でreturn文を宣言することで設定できる。
・キーワード引数とは、パラメータを任意にしたいときに使う引数。
キーワード引数の定義の仕方
def 関数名 ( key値 = value値):
処理内容
今回は、スコープ周りの話を始めていこうと思います。
3.5 スコープ
スコープというのは、変数の有効範囲のようなものです。もう少しちゃんとした言い方をすると、ある変数や関数などを参照できる範囲のことです。Pythonに限らず、ほとんどのプログラミング言語にあるもので、重要な考えになっています。
3.5.1 ローカルスコープとグローバルスコープ
スコープには、2種類のスコープがあります。それがローカルスコープとグローバルスコープです。
ローカルスコープとは、関数呼び出し時に設定されるパラメータと変数が格納されるスコープのことを指します。
一方、グローバルスコープとは、すべての関数の外で代入された変数が格納されるスコープのことを指します。
言葉だけではわかりにくいと思うので、実際に見てみましょう。
def main():
local_x = 10
local_y = 20
print(add(local_x,local_y))
print(add(global_a,global_b))
# print(num1,num2) 未定義エラーになる
def add(num1 , num2 ):
# print(local_x,local_y) 未定義エラーになる
print(num1 , num2)
print(global_a, global_b)
return num1 + num2
global_a = 10
global_b = 12
main()
# print(local_x,local_y) 未定義エラーになる
# print(num1,num2) 未定義エラーになる
このコードは、コメントアウトを外すと、その箇所は未定義エラーになります。ローカルスコープは上記の場合2つあります。1つはmain関数内、もう1つはadd関数内がローカルスコープということになります。
グローバルスコープは、すべての関数外で代入された変数が格納されるスコープなので、上記の場合、main関数とadd関数以外の範囲がグローバルスコープということになります。
3.5.2 ローカル変数とグローバル変数
ローカルスコープとグローバルスコープについてわかりましたでしょうか?
続いては、ローカル変数とグローバル変数についてです。といっても、これらはローカルスコープとグローバルスコープがわかっていれば難しくありません。
ローカル変数とは、ローカルスコープ内で定義された変数のことを指し、グローバルスコープとは、グローバススコープ内で定義された変数のことを指します。
先ほどの例でみてみると、local_x、local_yはmain関数のないのローカル変数、num1、num2はadd関数のローカル変数、そして、global_a、global_bがグローバル変数ということになります。
【Point】
・関数呼び出し時に設定されるパラメータと変数が格納されるスコープのことをローカルスコープという。
・すべての関数の外で代入された変数が格納されるスコープのことをグローバルスコープという。
・ローカルスコープで定義された変数をローカル変数といい、グローバルスコープで定義された変数をグローバル変数という。
3.5.3 ローカル変数とグローバル変数の参照範囲
ローカル変数とグローバル変数について、もう少し説明をしていきます。
先ほども少し書きましたが、ローカル変数とグローバル変数には、それぞれ参照可能な範囲があります。
そのルールは、以下の通りです。
【それぞれの参照可能範囲】
1. ローカル変数は、グローバルスコープでは参照できない。
2. ローカル変数は、別のローカルスコープでは、参照できない。
3. グローバル変数は、グローバルスコープと、ローカルスコープの両方で参照できる。
先ほどの例を参考にしながら、確認していきましょう。
def main():
local_x = 10
local_y = 20
print(add(local_x,local_y))
print(add(global_a,global_b))
# print(num1,num2) 未定義エラーになる
def add(num1 , num2 ):
# print(local_x,local_y) 未定義エラーになる
print(num1 , num2)
print(global_a, global_b)
return num1 + num2
global_a = 10
global_b = 12
main()
# print(local_x,local_y) 未定義エラーになる
# print(num1,num2) 未定義エラーになる
まず1番ですが、これは最後のコメントアウトしている2行に当たります。
local_x,local_yはそれぞれmain関数で定義されているローカル変数で、num1,num2はadd関数のローカル変数です。そのため、グローバル変数では使用できないため、未定義エラーとなります。
次に2番ですが、これはmain関数の最後の行と、add関数の最初の行になります。
最後に3番ですが、これはmain関数の4行目とadd関数の3行目になります。
このように、グローバル変数はどこのスコープからでも参照できますが、ローカル変数は、それを定義したローカル変数内でしか参照できません。
ここで「グローバル変数とローカル変数で同じ変数名を付けたらどうなるの?」と疑問に思った方がいるかもしてません。
実際に見てみましょう。
def main():
x = 'local_x'
y = 'local_y'
print(x)
print(y)
x = 'global_x'
y = 'global_y'
main()
print(x)
print(y)
【実行結果】
local_x
local_y
global_x
global_y
実行結果からわかる通り、同じ変数名を付けても、プログラム上は問題ありません。ただし、優先されるのはローカル変数のほうが優先されます。
しかし、このようなコードは読みにくくなってしまうため、一般的にグローバル変数とローカル変数は別の名前を定義します。
【Point】
ローカル変数は、グローバルスコープでは参照できない。
ローカル変数は、別のローカルスコープでは、参照できない。
グローバル変数は、グローバルスコープと、ローカルスコープの両方で参照できる。
3.6 global文
ここまで、スコープとローカル変数、グローバル変数について勉強してきました。最後は、ローカルスコープ内でグローバル変数に値を代入する方法を説明します。
やり方は簡単で、global文というものを使うだけです。
【global文の使い方】
global グローバル関数名
実際に見てみましょう。
def main():
global x
x = 'change_x'
x = 'global_x'
print(x)
main()
print(x)
【実行結果】
global_x
change_x
main関数の1行目でglobal文を使用しています。実行結果から、main関数内では、ローカル変数のxとしてではなく、グローバル変数のxとしてあつかっていることがわかります。
さて、ここで変数のスコープがローカルなのか、グローバルなのかを見分ける方法を説明しましょう。
【変数のスコープの見分け方】
1. 変数がグローバルスコープで使われているなら、必ずグローバル変数になる。
2. 関数の中で、global文が使われていれば、その変数はグローバル変数になる。
3. そうでなく、関数の中で代入されていれば、その変数はローカル変数になる。
4. 代入されていなければ、グローバル変数になる。
実際の例を交えてみてみましょう。
def spam():
global eggs
print('start spam')
eggs = 'spam' # グローバル変数になる
def bacon():
print('start bacom')
eggs = 'bacon' # ローカル変数になる
print(eggs)
def ham():
print('start ham')
print(eggs) # グローバル変数になる
eggs = 42
print('start')
print(eggs)
spam()
bacon()
ham()
print(eggs)
【実行結果】
start
42
start spam
start bacom
bacon
start ham
spam
spam
1番は、グローバルスコープで使用されている変数のことなので、spam関数、bacon関数、ham関数の外で使用されている変数は、すべてグローバル変数として扱われます。
2番は、spam関数内の変数eggsが該当します。global文を使用しているため、spam関数内でeggsはグローバル変数として扱われます。
3番については、bacon関数内の変数eggsが該当します。bacon関数内の変数eggsは、global文を使用する前に代入をしているため、ローカル変数として扱われます。
最後の4番については、ham関数内の変数eggsが該当します。
こちらは、変数eggsに値を代入せずに使用しているため、グローバル変数扱いになります。
また、関数の中で、変数は常にローカルか常にグローバルかのどちらかになります。そのため、同じ関数の中でeggsというローカル変数を使用した後に、eggsというグローバル変数を使用する方法はありません。
【Point】
・ローカルスコープ内でグローバル変数に値を代入したときは、global文を使うとよい。
【変数のスコープの見分け方】
1. 変数がグローバルスコープで使われているなら、必ずグローバル変数になる。
2. 関数の中で、global文が使われていれば、その変数はグローバル変数になる。
3. そうでなく、関数の中で代入されていれば、その変数はローカル変数になる。
4. 代入されていなければ、グローバル変数になる。
まとめ
今回は、スコープについて勉強していきましたが、いかがでしたか?
まとめると、こんな感じでした。
【まとめ】
・変数には2つのスコープがあり、ローカルスコープとグローバルスコープを呼ばれる。
・ローカルスコープで代入された変数をローカル変数といい、グローバルスコープで代入された変数をグローバル変数という。
・ローカルスコープでグローバル変数に値を代入したい場合は、global文を使用する。
・変数がローカル変数なのか、グローバル変数なのかを見分けるルールがある。
次回は例外処理に入っていきます。ではでは。
P.S.
最近ボルダリングを始めてみました。