Pythonでは関数にある動きを定義して何回でも使える便利な機能があります。
関数の定義から引数、スコープ、例外処理に関するメモを残しておきます。
もくじ
関数とは、処理を一塊にして定義されているものだとイメージしてください。
メソッドとも言います。
関数に何か値を渡して、そのまま実行することも可能ですが、返り値として値を返す事も可能です。
文章だと少し分かりづらいと思いますので、実際に作成して見てみます。
関数の定義は以下の様に行います。
def 関数(引数):
処理
例として、say_hello関数を以下作成します。
def say_hello(): print("Hello")
1行目でsay_hello()関数を宣言して、2行目で”hello”をprintする処理を定義しました。
実際に使ってみると、
say_hello() >>>Hello
Helloが表示されました。
次に、say_helloの返り値としてHelloを定義してみます。
def say_hello(): return "Hello"
return 返り値
とする事で、返り値の設定が出来ます。
これで、say_helloは”Hello”をprintで表示させる関数から、”Hello”と言う値を返す関数になりました。
say_hello()をprintで表示させてみます。
print(say_hello()) >>>Hello
関数に引数を設定する事で、値を関数に渡し処理を行う事が出来ます。
def say_hello(a): return a + " Hello"
上では引数aを設定し、”a Hello”を返す関数を作成しました。
実行してみます。
print(say_hello("Python")) >>>Python Hello
次に位置引数を作成します。
def plus(num1,num2): return num1 + num2
引数にnum1とnum2を設定し、足し合わせた数を返す関数を作成しました。
printしてみます。
print(plus(2,7)) >>>9
2がnum1に7がnum2に代入され、足し合わされて9が返ってきました。
この引数の順番は守らなくてはなりません。
また、引数の数が揃っていないと以下の様にTypeErrorが出てしまいます。
print(plus(2,7,1)) >>>TypeError: plus() takes 2 positional arguments but 3 were given
この様な引数を位置引数と言います。
以下様なコードは、
def plus(a,b,c,d,e): return a + b + c + d + e print(plus(1,2,3,4,5)) >>>>15
必ず5つ値を用意しないとエラーになりますので、
def plus(nlist): total = 0 for n in nlist: total += n return total print(plus([1,2,3,4,5,6]))
上の様に引数で受け取る値をリストにして、リストの中の値を全て足し合わせるというコードにした方が良いでしょう。
次にキーワード引数をみてみます。
def div(a,b): return a / b print(div(2,4)) >>>0.5 print(div(4,2)) >>>2
aをbで割って返すdiv関数を作成しました。
div(2,4)とすると、引数aに2が代入され、引数bに4が代入され0.5が返るのですが、div(4,2)とすると引数aに4が代入され、引数bに2が代入される為2が返ってきます。
ここまでは位置引数と同様なのですが、どの引数にどの値を渡すのか指定する事が出来ます。
print(div(b=4,a=2)) >>>0.5
上は代入する変数を指定していますので、引数の値を指定する順番が違っていても前者が優先されます。
関数を作成する際に、値を指定しておけるデフォルト引数というものもあります。
def div(a=10,b=2): return a / b
上はaに10bに2と言う値を最初から持っている関数を作成しました。
その為、渡す引数無しで実行すると、
print(div()) >>>5.0
10 / 2 の 5.0 が返ってきました。
位置引数やキーワード引数を渡す事で、デフォルト引数に上書きする事が出来ます。
print(div(2,4)) >>>0.5 print(div(b=4,a=2)) >>>0.5
次に位置引数とキーワード引数が混ざった関数の定義と、実行時の値の指定方法を見ていきます。
def func(a,b,c,d=0,e=0): print(a,b,c,d,e)
a,b,cは値の指定がなく、d,eはデフォルト引数になっています。
定義の時の注意点としては、まず位置引数を指定し、次にデフォルト引数を指定します。
順番を無視してしまうと、エラーがでます。
func(10,20,30,e=100) >>>10 20 30 0 100 func(10,20,d=10,e=20,c=100) >>>10 20 100 10 20
実行時も同様に、まず位置引数を指定し、その後キーワード引数を指定します。
関数に渡す値が不明な時は可変長引数を使います。
def func(*args): print(args)
引数argsの前に”*”をつけると、引数を幾つでも渡せる様になります。
実行してみます。
func(1,2,3,4,5,6,7,8) >>>(1, 2, 3, 4, 5, 6, 7, 8)
可変長引数はタプルとしてまとめられます。
引数にリストやタプルを渡すと、
func([1,2,3,4,5,6,7,8]) >>>([1, 2, 3, 4, 5, 6, 7, 8],) func((1,2,3,4,5,6,7,8)) >>>((1, 2, 3, 4, 5, 6, 7, 8),)
タプルの一つ目の要素としてまとめられます。
これを分解したいと言うときは、下の様にタプルの前に”*”をつけます。
func(*(1,2,3,4,5,6,7,8)) >>>(1, 2, 3, 4, 5, 6, 7, 8)
可変長引数は必ず、位置引数の後に記載する必要があります。
def func(a,b,*args): print(a,b) print(args)
func(1,2,3,4,5) >>> 1 2 (3, 4, 5)
1はaに2はbに代入され、残った3,4,5が可変長引数*argsにタプルでまとめられました。
def func(**kwargs): print(kwargs)
引数kwargsの前に”**”をつけると、キーワード引数を幾つでも渡せる様になります。
func(a=2,dfg=3,b=4) >>>{'a': 2, 'dfg': 3, 'b': 4}
実行すると辞書型でa=2,dfg=3,b=4がまとめられました。
辞書型の変数を渡したい場合は下の様に変数に”**”を付けて渡し展開させる事が出来ます。
d = {"a":1,"b":2,"cdf":4} func(**d) >>>{'a': 1, 'b': 2, 'cdf': 4}
上の手法を使う事で、ファイルパスの作成が簡単になります。
まず、辞書型に情報を入れておきます。
d = {"drive":"W","sec":"sec06","filename":"learning13","extension":"py"}
そして.formatで展開します。
s = "{drive}:/{sec}/{filename}/{extension}".format(**d) print(s) >>>W:/sec06/learning13/py
def func(a,b,*args,f=0,**kwargs): print(a,b) print(args) print(f) print(kwargs)
位置引数、可変長位置引数、キーワード引数、可変長キーワード引数の順番で指定していきます。
実行してみます。
func(1,2,3,4,5,f=9,g=10,h=11) >>> 1 2 (3, 4, 5) 9 {'g': 10, 'h': 11}
a,bに1,2が渡された後、余っている3,4,5は*argsにまとめられます。
f=9がキーワード引数fを上書きし、余ったg=10,h=11が**kwargsにまとめられました。
尚、下の様にf=9を記載しないとデフォルトの0がprintされます。
func(1,2,3,4,5,g=10,h=11) >>> 1 2 (3, 4, 5) 0 {'g': 10, 'h': 11}
関数でも変数を指定する事が出来たのですが、関数内の変数や関数外での変数は参照できる範囲が決まっています。
その範囲の事をスコープと言います。
num = 10 #global def func(): num = 100 #local print("local",num)
以下のコードはそれぞれ、変数numをprintしています。
func() print("global",num) >>> local 100 global 10
func()内のprintは関数内にあるnumを出力し、関数外のprintは関数外にあるnumを出力している事が分かります。
もし、関数内でglobal空間にある変数を変更したい場合は、下の様に global 変数
をつける事で編集可能です。
num = 10 def func(): global num num = 100 print("local",num)
再度実行してみます。
func() print("global",num) >>> local 100 global 100
global変数が変更された事がわかるかと思います。
関数内で何も指定しなければ、グローバル変数を参照することは可能です。
num = 10 def func(): print("local",num) func() print("global",num) >>> local 10 global 10
尚、グローバル空間からローカル変数を参照することは出来ません。