Pythonの関数

beanz (2008年11月20日 01:16) | コメント(0) | トラックバック(0)

Pythonにも当然関数を定義したり定義した関数を呼び出したりする機能がある。
簡単な関数定義は以下のような感じだ

def f(argv):
  print argv

そして

f("Hello")

みたいにして呼び出す事が出来る。ちなみにPythonはPerlやPHPとは違い先に定義しておかないと呼び出す事は出来ない。なので

f("Hello")
def f(argv):
  print argv

のような書き方だとエラーになってしまう。

上のような関数だと関数の中でいきなり出力してしまっているので出力以外の目的には全く使えない。
もう少しつぶしの効いた関数にするには以下のようにした方がいい。

def f(argv):
  return argv

こうすれば関数の中の処理の結果が呼び出し元に返ってくる。その後どう使うかはこちら次第という事だ。
例えばさっきのように出力する事も出来るし変数に格納しておいて後で使い回す事も出来る。
ところで上記コードの"argv"の部分を引数というが、Pythonでは関数定義の時とその関数を呼び出す時は引数の数をあわせておかなければならない。
以下のようなコードはエラーになってしまう。

def f(num1, num2):
  return num1 + num2
a = f(10)

この場合は引数の数をきっちり揃えて以下のようにして呼び出さなければならない。

a = f(10, 20)

こうすれば変数aに30が格納される。
もちろんPythonの関数はもっともっと柔軟に定義する事が出来るし呼び出す事も出来る。
ただし引数をどうするかは、定義時と呼び出し時において同じような記述でも意味が全く違ってくるので時々頭が混乱してくる。
ここできちんと整理しておきたい。

まずは関数の定義から。
上のような引数が一つの時や二つの時以外にも。

def f(argv = "Hello"):

こんな書き方が出来る。ここでは引数のデフォルト値を設定している。
この関数を呼び出す時は引数を省略して呼び出す事が出来、その場合引数"argv"の値として"Hello"が使われる事になる。
引数を指定すればそっちが使われる。
デフォルト値の設定された引数はいくつでも指定できるが、デフォルト値の設定されていない引数の前には置く事は出来ない。

要は

def f(a, b = "Hello", c = "world"):

こんな書き方は出来るが。

def f(b = "Hello", c = "world", a):

これはNG。

引数が可変になる時はこう書く事が出来る。

def f(*args):

これは関数内部では"args"という一つのタプルとして扱われる事になる。
呼び出す時には

f(1,2,3,4,5,6,7)

と、引数はいくつでもOKだ。例えば任意の個数の数値を渡してそれらの平均値を計算したいといった時に使えたりする。
さらにこんな定義の仕方もある。

def f(**args):

こちらも同様に引数はいくつでも渡せるがこの場合はこんな風にして渡さないと駄目だ。

f(name = "ichiro", age = 35, unumber = 51)

これは関数内部では

{'age': 35, 'name': 'ichiro', 'unumber': 51}

このような辞書として処理される。
ここでちょっとややこしいのが関数定義の時もイコールを使って引数を指定していたがその時はデフォルト値の指定だった。呼び出し時のイコールはキーワード引数というものだ。定義時と呼び出し時では意味が違う。
アスタリスクを二つ使ったタイプは関数内部では辞書として扱われるが呼び出し時に辞書を渡す事は出来ない。ここでも混乱しそうだ。

f({'age': 35, 'name': 'ichiro', 'unumber': 51})

こんな呼び方は駄目。
さらに呼び出し時に引数の前に一つアスタリスクを付けたら

l = ["taro", "hanako", "ryota"]
f(*l)

このコードは

f("taro", "hanako", "ryota")

こう解釈される。単に

f(l)

と、こうした時との違いは"一つのリスト"を渡したのか"3つの文字列"を渡したのか、という違いになる。

例えば文字列の前にアスタリスクを付け

f(*"Hello")

こうしたら

f('H', 'e', 'l', 'l', 'o')

こうしたのと同じ結果になる。
辞書を渡したらキーだけが展開されて渡される事になる。
このアスタリスク一つ付けるという行為も定義時とでは意味が違う。
そして関数定義の段階では例えば以下のような書き方も出来てしまう。

def f(a, b = "Hello", *args, **kwd):

じゃあ、何でもありなのかと思えば

def f(a, b = "Hello", **kwd, *args):
def f(a, *args, b = "Hello", **kwd):

みたいな書き方は駄目だ。
まあ、あまり複雑にすると自分の頭が付いていけなくなるので程々にしておこう。

定義時、呼び出し時それぞれでのイコールとアスタリスクの使い方を今一度整理。

定義時は:
イコールはデフォルト値。
アスタリスクは可変数の引数を受け取れるようにする。

呼び出し時は:
イコールはキーワード引数。
アスタリスクはリストや文字列などのシーケンスを展開した状態で渡す。

てこと。

カテゴリ:

トラックバック(0)

トラックバックURL: http://blog.beanz-net.jp/beanz_mtos/mt-tb.cgi/26

コメントする