3-4 自作関数とライブラリを作ってみよう
3-1.ExcelのSUMも関数だでは,配列を引数としてその配列の合計値を計算するSUM(arg)関数を作成しました.ここでは,もう少し自作関数に焦点を当て,戻り値が無い関数や複数引数などを勉強していきたいと思います.
戻り値 = 関数(引数)
先程のSUM(arg)で言えば,SUMが関数,argが引数,出力された結果が戻り値になります.では,以下のようなケースはどうでしょうか.
戻り値のないSUM(arg)
- def SUM(arg):
- j = 0
- for i in arg:
- j += i
- print(j)
-
SUM_2.py
- def SUM(arg):
- j = 0
- for i in arg:
- j += i
- return j
-
左の関数は関数内で配列argの合計値をprintする関数,右の関数は戻り値として配列argの合計値を戻り値として返す関数です.左の関数は上式の戻り値がありませんが,これも正常に機能します.戻り値というのはあくまでもオプションであり,関数のネスト内で実行された結果として生まれた変数を関数の外に吐き出すためのコードだと考えると良いでしょう.
(2) 複数の引数や戻り値
関数は一引数,一戻り値が絶対ではありません.複数引数,複数戻り値を使った関数も作成可能です.
(2) 複数の引数や戻り値
関数は一引数,一戻り値が絶対ではありません.複数引数,複数戻り値を使った関数も作成可能です.
複数引数と複数戻り値
- a = 6
- b = 12
-
- def Multiply(a,b):
- c = a*2
- d = b/2
- return c,d
- c,d = Multiply(a,b):
- print(c)
- print(d)
-
12 6
複数戻り値を用いた関数を作成する場合はカンマで関数の外へ返す変数を区切ります.そして,関数を使用する際にはc,d = Multiply(a,b)のように出力される変数を同様にカンマで区切ります.
(3) 自作ライブラリを作ってみよう
ここまでで,簡単な関数の作り方が分かったかと思います.ここでは,importで呼び込みを行なうことで使用可能になるmathやitertoolsのような外部ライブラリを自作してみます.
ここまでで,簡単な関数の作り方が分かったかと思います.ここでは,importで呼び込みを行なうことで使用可能になるmathやitertoolsのような外部ライブラリを自作してみます.
はじめにライブラリになる.pyファイルを作成します.以下のようなファイルを作成してみましょう.
test_library.py
- def SUM(arg):
- j = 0
- for i in arg:
- j += i
- return j
-
- def multiply(a,b):
- c = a*2
- d = b/2
- return c,d
-
続いて,作成したtest_library.pyと同じ場所に本体のpyファイルを作成します.ここで,先程作成したライブラリとなるpyファイルをimportで呼び込みます.
main.py
- import test_library as TL
-
- a = [5,2,7,45]
- b = 2
-
- result_A = TL.SUM(a)
- result_B, result_C = TL.Multiply(a,b)
- print(result_A,result_B,result_C)
-
59 [5, 2, 7, 45, 5, 2, 7, 45] 1.0
ここまでで,別のpyファイルであるtest_library.pyに関数を作成し,importでライブラリを呼び込むことができたはずです.こうすることで一つのpyファイルに余計なことを書く必要はなく,キレイで分かりやすい実行ファイルを作ることができます.実際に作成した関数を実行しているpyファイルの名前をmain.pyとしていますが,これはC言語でコードを書く際にmain{ }という書き方をする名残です.ライブラリをサブとして,実行ファイルをメインという名前にする意図もあります.as TLというのはライブラリの名前を略称にするために使います.ライブラリ名に沿った略称にしましょう.例えば,numpyを使う際にimport numpy as npとするのはお約束です.こうすることでnumpyの関数を使う度にnumpy.関数名と度々打たずにnp.関数名とすることができます.
更に,水理計算(hydraulics),費用計算(costs),グラフ出力(graph)など用途によって関数ライブラリを作成し,import hydraulics, costs, graphと宣言することで各ライブラリの関数を使用することができます.このようなライブラリ構造とすることで,プログラム全体の構造が非常にわかりやすくなります.
なお,main.pyのリストaを*2すると,リスト内の数値を2倍にするのではなく,同じリストを2つにして伸ばす処理が行われます.この点は少し普通の感覚とは違うので注意です.一方,これを上手く活用するとa = [0]*10 = [0,0,0,0,0,0,0,0,0,0]というゼロのリストも作成可能です.
(4) ローカル変数
関数defのようにインデント(字下げ)によって区別されたネストにおいて,ネスト内で宣言された変数はネスト内でのみ有効です.これをローカル変数と呼び,ローカル変数が有効となる範囲をスコープと言います.ローカル変数をネスト外で呼び出そうとするとエラーとなったり,ネスト外に同じ名前の変数があればそれが参照される事となったりしてしまいます.ここも初学者は間違いやすいので注意しましょう.以下にローカル変数を考慮しないコードの書き方と考慮した書き方を示します.
関数defのようにインデント(字下げ)によって区別されたネストにおいて,ネスト内で宣言された変数はネスト内でのみ有効です.これをローカル変数と呼び,ローカル変数が有効となる範囲をスコープと言います.ローカル変数をネスト外で呼び出そうとするとエラーとなったり,ネスト外に同じ名前の変数があればそれが参照される事となったりしてしまいます.ここも初学者は間違いやすいので注意しましょう.以下にローカル変数を考慮しないコードの書き方と考慮した書き方を示します.
ローカル変数を知らない書き方
- def Global_Local(a):
- a = [ ]
- j = 2 #Local variable
-
- for i in range(10):
- a.append(j*i)
-
- return a
- print(Global_Local(a))
- print(j)
-
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18] Name Error: name 'j' is not defined
例にあるようにGlobal_Local(a)という関数内において変数jはその関数内のみで有効なローカル変数として機能しています.ここで,例のように関数の外でprint(j)によってj=2を呼び出そうとするとName Error: name 'j' is not defined = 「jなんて変数は定義されていない」と表示されます.これはローカル変数が関数内のみで有効なためであり,関数外で機能するグローバル変数では無いからです.ではどうすれば変数jはグローバル変数として機能するかというと,それはreturn a,jとして関数Global_Local(a)というスコープから脱出させてあげることです.あるいは関数の外でj=2を宣言し,Global_Local(a,j)としてjを引数として読み込ませてあげることです.