##1. メソッド(関数)を宣言する
def sample_func_1(text : str) -> str:
add_text = "追加した文字列"
return (text + add_text)
def sample_func_2(text : str) -> str:
add_text2 = "追加した文字列バージョン2"
return (text + add_text2)
##2. 辞書型(dict)オブジェクトのValueに、関数を括弧を付けずに記述する
func_dict = {
'label_1' : sample_func_1,
'label_2' : sample_func_2
}
##3. 辞書型オブジェクトKeyラベル名で、関数を呼び出して実行する
辞書(dict)のvalue値として、格納されているのは、関数(メソッド)オブジェクトそのものです。
そのため、関数(メソッド)を実行するには、辞書(func_dict)のvalue値に、引数を受け取る丸括弧("( )")を付ける必要があります。
丸括弧("( )")を付けないで、辞書(dict)のvalue値として格納されている関数(メソッド)「それ自体」を呼び出した場合の結果は、以下になります。
func_dict['label_1']
<function sample_func_1 at 0x100bafb80>
上記のコードで辞書から呼出した関数(メソッド)を実行するには、引数を受け取る丸括弧("( )")をつける必要があります。
func_dict['label_1']()
なお、funct_dictが引数を1つ以上、受け取るメソッドである場合は、引数を与えないで関数呼出しをすると、エラーが出ます。
定義したメソッド(関数)は、str型のオブジェクトを引数を受け取る関数でした。
引数に適当な文字列を渡して、func_dict内に格納されているメソッド(関数)を実行してみます。
func_dict['label_1']("vxw")
# 実行結果
'vxw追加した文字列'
#####( 参考 )
func_dict
# 実行結果
{'label_1': <function sample_func_1 at 0x100bafaf0>, 'label_2': <function get_text_from_ppt at 0x100bafa60>}
func_dict['label_1']
<function sample_func_1 at 0x100bafb80>
type(func_dict['label_1'])
# 実行結果
<class 'function'>
type(func_dict['label_1']())
# 実行結果
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sample_func_1() missing 1 required positional argument: 'text'
type(func_dict['label_1']("giho"))
# 実行結果
<class 'str'>
func_dict['label_1']("giho")
# 実行結果
'giho追加した文字列'
returned_value = func_dict['label_1']("giho")
returned_value
# 実行結果
'giho追加した文字列'
###( 参考にしたWebページ )
##( 使いみち )
今回、紹介した方法を用いることで、辞書型オブジェクトに定義されたKeyの値に応じて、そのKeyに対応する関数(メソッド)を呼び出すことができます。
データを処理する流れのなかで、条件に応じて、呼び出すべき適切な関数(メソッド)が切り替わるロジックが必要な場面で、役に立ちます。
基本的な例として、読み込んだファイルの拡張子の内容に応じて、そのファイルに所要の処理を行う関数(メソッド)を動的に選び出して呼出して実行する場面、などが考えられます。
PDFファイルやWordファイル、Excelファイルから、テキスト文字列のみを切り抜いてデータ取得するコードは、以下のWebページで紹介されています。
- deecode blog 「[Python] Word/Excel/PowerPoint/PDFからテキスト抽出するライブラリ・サンプルコード」
- @butadaさんのQiita記事 「pdf/docxファイルからのテキストマイニング」
また、受け取ったファイルの絶対パスから、パスの末尾に記載されている拡張子をPythonで取得するコードは、以下で取り上げられています。
file_abstract_path = 'C:\\foo\\bar\\test.txt'
import os.path
root, ext = os.path.splitext(file_abstract_path)
# 拡張子は、extに格納されている。
print(ext)
# 上の例では、".txt"が出力される。
def get_text_from_txt(filename : str) -> str:
filenameとして受け取ったパスに格納されているテキストファイルをreadして、テキストを*str*オブジェクトとして取得して、返り値として出力する処理
return text
def get_text_from_pdf(filename : str) -> str:
filenameとして受け取ったパスに格納されているPDFファイルをreadして、テキスト文字列を抜き出して、ひとつの*str*オブジェクトに連結して、返り値として出力する処理
return text
def get_text_from_word(filename : str) -> str:
filenameとして受け取ったパスに格納されているWordファイルをreadして、テキスト文字列を抜き出して、ひとつの*str*オブジェクトに連結して、返り値として出力する処理
return text
def get_text_from_excel(filename : str) -> str:
filenameとして受け取ったパスに格納されているExcelファイルをreadして、テキスト文字列を抜き出して、ひとつの*str*オブジェクトに連結して、返り値として出力する処理
return text
func_dict = {
'txt' : get_text_from_txt,
'pdf' : get_text_from_pdf,
'word' : get_text_from_word,
'excel' : get_text_from_excel
}
( 事後追記 )
以下の記事でやってみました。
・ 「PDF・Word・PowerPoint・Excelファイルからテキスト部分を一括抽出するメソッド」
##( 備考 )
辞書のValueに関数(メソッド)を格納するときに、関数に括弧を付けると、以下のエラーが発生する。
関数の実行を行おうとしていると、解釈されてしまうため。
func_dict = {
'label_1' : sample_func_1(),
'label_2' : sample_func_2()
}
# 実行結果
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: sample_func_1() missing 1 required positional argument: 'text'
辞書を定義する上のコードのなかで、*sample_func_1()*の括弧のなかに特定の引数を与えると、辞書は定義できる(エラーは起きない)。
しかし、辞書のValueに格納された関数は、辞書を定義する際に受け取った引数しか、受け取ることのできない関数になってしまう。
( 辞書の定義 )
func_dict = {
'label_1' : sample_func_1("abc"),
'label_2' : sample_func_2("def")
}
( 辞書内の関数の呼出し実行 )
func_dict辞書内で、Key"label_1"に対応するValueとして定義されている、関数*sample_func_1("abc")*が、引数"abc"を与えられた状態で、実行された。
func_dict['label_1']
# 実行結果
'abc追加した文字列'
func_dict['label_1'](を評価すると)は、すでに返り値として、str型のインスタンス*'abc追加した文字列'*を返している。そのため、*func_dict['label_1']*にさらに括弧を付けると、TypeError: 'str' object is not callableエラーが起きる。
func_dict['label_1']()
# 実行結果
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
func_dict['label_1']("abc")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
unc_dict['label_1']('abc')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object is not callable
##( 備考2 )
辞書のValにテキスト文字列を格納して、evalとexecを用いて、関数をよびだせる。
しかし、キーボードのストローク数が増えてしまい、エレガントではない。
func_dict = {
'label_1' : "sample_func_1({arg})",
'label_2' : "sample_func_2({arg})"
}
func_dict
# 実行結果
{'label_1': 'sample_func_1({arg})', 'label_2': 'sample_func_2({arg})'}
func_dict['label_1']
# 実行結果
'sample_func_1({arg})'
expression = func_dict['label_1'].format(arg="'123'")
expression
# 実行結果
"sample_func_1('123')"
eval(expression)
# 実行結果
'123追加した文字列'
result = eval(expression)
result
# 実行結果
'123追加した文字列'
add_text = "result2="
text = add_text + expression
text
# 実行結果
"result2=sample_func_1('123')"
exec(text)
result2
# 実行結果
'123追加した文字列'
##( 続編記事 )
・ 「【@registerデコレータ使用篇】Pythonの関数を辞書(dict)のValueに格納して、Keyに応じた関数を呼出す」