関数について
ここでは、もう少し関数について詳しく説明することにします。
まず、次の例をみてみましょう。
code: python
def func():
""" これはドキュメント文字列(docstrings)です
コメントと違って実行時にアクセスすることができます。
"""
pass
print(dir(func))
print(func.__doc__)
Pythonスクリプト、クラス、関数にはドキュメント文字列で説明などをドキュメント化することができます。これは3重引用符(""" ... """、''' ... ''')で囲まれた文字列で、コメントとは異なり実行時にアクセスすることができます。ドキュメント文字列はインタラクティブなヘルプユーティリティ help()が読み取ります。
次の例をみてましょう。
code: python
c = sum(data)
print(f'{c}')
print(sum)
def sum(a, b):
return a + b
c = sum(1,2)
print(f'{c}')
print(sum)
はじめに出てくる sum() は Python の組み込み関数で、与えたリストを合計するものです。
注目する点は、そにあとに同じ名前で関数sum() を定義していることです。
これは、エラーにはならず問題なく実行できてしまいます。
code: bash
$ python sample.py
15
<built-in function sum>
3
<function sum at 0x7fb5c6dc6e18>
はじめの print(sum) では、組み込み関数であると表示され、
次では見慣れない16進数が表示されていますね。
任意の名前で関数を定義することができますが、
バグを混入させないためにも組み込み関数と同じ名前を使用しないことです。
関数オブジェクト
Python で括弧やパラメタを与えずに関数名だけを実行するとエラーにはなりません。
code:python
>> def greeting(name='Guido'):
... print(f'Hello {name}!')
...
>> greeting
<function greeting at 0x1053eb730>
この場合、オブジェクトIDを表示します。
関数オブジェクトを変数に代入する
関数オブジェクトは変数に代入して使うこともできます。
次の例は単純に別名にして呼び出しているものです。
code: 0101_function_alias.py
def greeting(name='Guido'):
print(f'Hello {name}!')
hello = greeting
hello('Python')
これを利用して関数をリストや辞書に登録しておき、入力値に応じて実行する処理を変更することができます。
code: 0102_function_as_table.py
def squre(n):
return(n**2)
def cube(n):
return(n**3)
# data の要素が偶数なら squre, 奇数なら cube を実行する
# 単純な方法
for v in data:
if v%2 == 0:
result = squre(v)
print(f'squre({v}):', result)
else:
result = cube(v)
print(f'cube({v}):', result)
# より洗練された方法
for v in data:
n = v%2
print(f"{action.__name__}({n}):", action(v))
こうした実装方法はif文などによる条件判断のロジックをプログラム中にコーディングしなくても、データとして外部に保存できるようになるということです。つまり、同じコードで別の処理をするプログラムを書くことができます。
例えば、「ポケモン」などのゲームで「赤」と「青」などシリーズがあったと記憶していますが、これはデータ部分を変えているだけでプログラムはほとんど同じだったりするわけです。
(不確かな情報ですが...)
私が新人だった頃、先輩から常々言われたことの一つに、
「ロジックを書くな! テーブルで表現しろ!」
といったものがあります。
関数を引数として他の関数に渡す
関数を引数として他の関数に渡すことができます。よく知られた例で言えば、Python の組み込み関数 help() があります。
help() は引数で与えた関数の docstrings(三連引用符:triple quotes 、シングルクォートもしくはダブルクォートを3つ続けて囲んだ文字列)を表示するものです。
code: python
def greeting(name):
""" there are comments for greeting().
argument: name
"""
print(f'Hello {name}!')
help(greeting)
このことを利用して、実行時に呼び出す関数とデータを、引数として受け取る関数を定義してみましょう。
code: 0103_function_as_callback.py
def greeting_english(name):
print(f'Hello {name}!')
def greeting_french(name):
print(f'Bonjour {name}!')
def handler(func, *args):
return func(*args)
handler(greeting_english, 'Python')
handler(greeting_french, 'Python')
関数handler()は、第1引数が関数オブジェクト、次の引数はその関数への引数を受取り、与えられた関数オブジェクトを実行した結果を返しています。こうした関数をコールバック関数(Callback Function) と呼びます。
ここで、*args は可変長引数を表しているのですが、
次の節でもっと詳しく説明していくことにします。