def【関数定義】3.5 / 3.8return【関数の戻り値】3.8lambda【ラムダ式 (無名関数)】 def【関数定義】3.5 / 3.8メモ 構文 例引数の種類 デコレータ ジェネレータ関数 関数の呼び出し クラスメソッド・静的メソッド 特殊属性 メモ関数・メソッドの定義 関数はオブジェクト 複数の戻り値可 (参照:return【関数の戻り値】) 引数には位置引数・可変長引数 (可変長位置引数) ・キーワード引数・可変長キーワード引数 を定義可能 (構文・例 参照) デコレータを指定することで、既存関数の前後に処理を追加・戻り値の変更が可能 〔 例 〕引数なしのデコレータ:入れ子の関数を定義引数ありのデコレータ:上記をさらに入れ子にした関数を定義 引数・戻り値にアノテーション指定可 (チェック・ドキュメンテーションに利用可能・例参照) 関数名はスネークケースを推奨( PEP8:Naming Conventions - Function and Variable Names (英語)) ジェネレータ関数については、yield【ジェネレータ関数・一時停止】参照 関数の呼び出し リスト等の各要素を分解 (アンパック) して、引数に指定可 〔 例 〕list【リスト型】・tuple【タプル型】等: * を指定 (辞書型に指定:キーのみがアンパック) 〔 list【リスト型】のアンパック ・tuple【タプル型】のアンパック 〕dict【辞書型】:** を指定 (キー:引数名 / 値:引数値) 〔 dict【辞書型】のアンパック 〕複数指定可 3.5 引数の最後のカンマ (,) は無視 〔 例 〕 キーワード引数名はカッコ等で修飾不可 3.8 〔 例 〕 クラスメソッド・静的メソッドデコレータに下記を指定 クラスメソッド:@classmethod【クラスメソッド】 静的メソッド:@staticmethod【静的メソッド】 特殊属性 〔 例 〕 属性型備考__annotations__辞書型アノテーション引数キー:引数名戻り値キー:"return"__closure__タプルクロージャで参照する自由変数等__closure__[n].cell_contents上記自由変数等の個々の値__code__オブジェクトコードオブジェクト__defaults__タプルデフォルト値__dict__辞書型マッピングオブジェクト属性__doc__文字列ドキュメンテーション文字列__globals__辞書型関数のグローバル変数__kwdefaults__辞書型キーワード引数のデフォルト値__module__文字列モジュール名__name__文字列関数名__qualname__ 3.3文字列関数パスへのドット名表記関連return【関数の戻り値】 lambda【ラムダ式 (無名関数)】 yield【ジェネレータ関数・一時停止】 外部リンクPython 言語リファレンス関数定義呼び出し (call)標準型の階層 Python チュートリアル関数を定義する関数定義についてもう少し関数のアノテーション 用語集引数 (argument)parameter PEP Index (英語)PEP 448 -- Additional Unpacking GeneralizationsPEP 3107 -- Function AnnotationsPEP 318: 関数とメソッドのためのデコレータPEP 318 -- Decorators for Functions and Methods 構文 [@ デコレータ名 (複数:新規行)] def 関数名([引数 (複数:カンマ区切り)][,])[->戻り値アノテーション]: 関数処理1 (1行) 関数処理2 (複数行可) デコレータ名nドット (.) 指定可能 引数 引数位置引数 (値 のみで呼び出し可) *引数 (タプル型)可変長引数・可変長位置引数 (通常 *args 使用) 引数キーワード引数 (位置引数より後に定義:引数=値 で呼び出し) **引数 (辞書型)可変長キーワード引数 (通常 **kwargs 使用) * のみ可変長引数を使用せずキーワード引数との区切りとして指定 (これより後は、キーワード引数としてのみ有効) 〔 例 〕 / のみこれより前は、位置引数としてのみ有効 3.8 〔 例 〕 引数 = デフォルト値デフォルト値指定 引数: 引数アノテーション引数アノテーション指定 関数処理n (どちらか1つを指定)関数の処理 例 # 引数なし・デフォルト値 def func_0(): print("func_0()") func_0() def func_2(p1, p2 = 2): print("func_2", p1, p2) func_2(10, 20) func_2(100) func_2(p2 = 22, p1 = 11) 【出力例】 func_0() func_2 10 20 func_2 100 2 func_2 11 22 # 各種引数 (1/3) def func_args(p1, p2, *args, p11 = 110, p12 = 120, **kwargs): print(p1, p2, args, p11, p12, kwargs) print("args =", end=" ") for arg in args: print(arg, end=" ") print() print("kwargs =", end=" ") for kw in kwargs: print(kw, kwargs[kw], end=" ") print("\n") func_args("a", 2) func_args("b", 2, 3) func_args("c", 2, 3, 4, p11=11, p12=12) func_args("d", 2, 3, 4, p101=101, p102=102) func_args("e", 2, 3, 4, p11=11, p12=12, p101=101, p102=102) 【出力例】 a 2 () 110 120 {} args = kwargs = b 2 (3,) 110 120 {} args = 3 kwargs = c 2 (3, 4) 11 12 {} args = 3 4 kwargs = d 2 (3, 4) 110 120 {'p101': 101, 'p102': 102} args = 3 4 kwargs = p101 101 p102 102 e 2 (3, 4) 11 12 {'p101': 101, 'p102': 102} args = 3 4 kwargs = p101 101 p102 102 # 各種引数 (2/3) def func_args2(p1, p2, *, p11 = 11, p12 = 12): print(p1, p2, p11, p12) func_args2("a", 2) func_args2("b", 2, p11=110, p12=120) # func_args2("c", 2, 3, 4) # TypeError 【出力例】 a 2 11 12 b 2 110 120 # 各種引数 (3/3) Python 3.8 def func_args31(p1, p2, p11=11, p12=12): print(p1, p2, p11, p12) def func_args32(p1, p2, /, p11=11, p12=12): print(p1, p2, p11, p12) def func_args33(p1, p2, /, p11=11, p12=12, *, p21=21, p22=22): print(p1, p2, p11, p12, p21, p22) func_args31("P1", "P2") # 出力:P1 P2 11 12 func_args32("P1", "P2") # 出力:P1 P2 11 12 func_args33("P1", "P2") # 出力:P1 P2 11 12 21 22 func_args31("P1", p2="P2") # 出力:P1 P2 11 12 #func_args32("P1", p2="P2") # TypeError 例外 #func_args33("P1", p2="P2") # TypeError 例外 func_args31("P1", "P2", "P11", "P12") # 出力:P1 P2 P11 P12 func_args32("P1", "P2", "P11", "P12") # 出力:P1 P2 P11 P12 func_args33("P1", "P2", "P11", "P12") # 出力:P1 P2 P11 P12 21 22 func_args31("P1", "P2", p12="P12", p11="P11") # 出力:P1 P2 P11 P12 func_args32("P1", "P2", p12="P12", p11="P11") # 出力:P1 P2 P11 P12 func_args33("P1", "P2", p12="P12", p11="P11") # 出力:P1 P2 P11 P12 21 22 func_args33("P1", "P2", "P11", "P12", p22="P22", p21="P21") # 出力:P1 P2 P11 P12 P21 P22 func_args33("P1", "P2", p22="P22", p21="P21", p12="P12", p11="P11") # 出力:P1 P2 P11 P12 P21 P22 #func_args33("P1", "P2", "P11", "P12", "P21") # TypeError 例外 # 呼び出し (1/2) アンパック def func_unpack(p1, p2, p3, p4, p5, p6): print(p1, p2, p3, p4, p5, p6) p2 = [2, 3] p5 = {"p5": 5, "p6": 6} func_unpack(1, *p2, 4, **p5) # 出力:1 2 3 4 5 6 # 呼び出し (2/2) def func_call(p1, p2=2): print(p1, p2) func_call("P1", "P2", ) # 出力:P1 P2 func_call("P1", ) # 出力:P1 2 #func_call("P1", (p2)="P2") # Pyhon 3.8 構文エラー # デコレータ (1/2) def trace(func): def trace_inner(*args): print("Trace:Start", func.__name__, args) result = func(*args) print("Trace:End", func.__name__) return result # 処理結果の返却 return trace_inner # 関数の返却 @trace def print_str(s): print(s) print_str("xyz") def trace2(func): def trace2_inner(*args): print("Trace2:Start", func.__name__, args) result = func(*args) print("Trace2:End", func.__name__) return result # 処理結果の返却 return trace2_inner # 関数の返却 @trace @trace2 def print_str2(s): print(s) print() print_str2("XYZ") 【出力例】 Trace:Start print_str ('xyz',) xyz Trace:End print_str Trace:Start trace2_inner ('XYZ',) Trace2:Start print_str2 ('XYZ',) XYZ Trace2:End print_str2 Trace:End trace2_inner # デコレータ (2/2) def trace_outer(start, end): def trace(func): def trace_inner(*args): print("Trace:Start", func.__name__, args) print("start = '" + start + "' end = '" + end + "'") result = start + func(*args) + end # 処理結果の変更 print("Trace:End", func.__name__) return result # 処理結果の返却 return trace_inner # 関数の返却 return trace # 関数の返却 @trace_outer("( ", " )") def func_user(s): return "< " + s + " >" print(func_user("xyz")) def trace2_outer(start, end): def trace2(func): def trace2_inner(*args): print("Trace2:Start", func.__name__, args) print("start = '" + start + "' end = '" + end + "'") result = start + func(*args) + end # 処理結果の変更 print("Trace2:End", func.__name__) return result # 処理結果の返却 return trace2_inner # 関数の返却 return trace2 # 関数の返却 @trace_outer("(1 ", " 1)") @trace2_outer("[2 ", " 2]") def func_user2(s): return "<< " + s + " >>" print() print(func_user2("XYZ")) 【出力例】 Trace:Start func_user ('xyz',) start = '( ' end = ' )' Trace:End func_user ( < xyz > ) Trace:Start trace2_inner ('XYZ',) start = '(1 ' end = ' 1)' Trace2:Start func_user2 ('XYZ',) start = '[2 ' end = ' 2]' Trace2:End func_user2 Trace:End trace2_inner (1 [2 << XYZ >> 2] 1) # アノテーション def func_annotation( p1: "引数1アノテーション", p2: "引数2アノテーション" = 20,) -> "戻り値アノテーション": print(p1, p2) return p1 + p2 print(func_annotation.__annotations__) 【出力例】 {'p1': '引数1アノテーション', 'p2': '引数2アノテーション', 'return': '戻り値アノテーション'} # 特殊属性 (1/2) def func_attribute( p1: "引数1アノテーション" , p2: "引数2アノテーション" = 20, *p3: "引数3アノテーション", p4: "引数4アノテーション" = 40, **kwargs: "引数5アノテーション") -> "戻り値アノテーション": """ドキュメンテーション文字列""" def func_inner(): print("func_inner.__name__=", func_inner.__name__) print("func_inner.__qualname__ =", func_inner.__qualname__) func_inner() return p1 + p2 print("func_attribute.__annotations__ =", func_attribute.__annotations__) print("func_attribute.__closure__ =", func_attribute.__closure__) print("func_attribute.__code__ =", func_attribute.__code__) print("func_attribute.__defaults__ =", func_attribute.__defaults__) print("func_attribute.__dict__ =", func_attribute.__dict__) print("func_attribute.__doc__ =", func_attribute.__doc__) print("func_attribute.__globals__ =", func_attribute.__globals__) print("func_attribute.__kwdefaults__ =", func_attribute.__kwdefaults__) print("func_attribute.__module__ =", func_attribute.__module__) print("func_attribute.__name__ =", func_attribute.__name__) print("func_attribute.__qualname__ =", func_attribute.__qualname__) func_attribute(1, 2) 【出力例】 func_attribute.__annotations__ = {'p1': '引数1アノテーション', 'p2': '引数2アノテーション', 'p3': '引数3アノテーション', 'p4': '引数4アノテーション', 'kwargs': '引数5アノテーション', 'return': '戻り値アノテーション'} func_attribute.__closure__ = None func_attribute.__code__ = <code object func_attribute at 0x~, file "~.py", line ~> func_attribute.__defaults__ = (20,) func_attribute.__dict__ = {} func_attribute.__doc__ = ドキュメンテーション文字列 func_attribute.__globals__ = {'__name__': '__main__', '__doc__': None, ~} func_attribute.__kwdefaults__ = {'p4': 40} func_attribute.__module__ = __main__ func_attribute.__name__ = func_attribute func_attribute.__qualname__ = func_attribute func_inner.__name__= func_inner func_inner.__qualname__ = func_attribute.<locals>.func_inner # 特殊属性 (2/2) def func_closure(): data_1 = [] data_2 = [] def func_inner(): n = len(data_1) + 1 data_1.append(n) data_2.append(n * n) return n return func_inner f = func_closure() print(f()) print(f()) print(f()) print("f.__closure__ =", f.__closure__) print("f.__closure__[0].cell_contents =", f.__closure__[0].cell_contents) print("f.__closure__[1].cell_contents =", f.__closure__[1].cell_contents) print(f()) print("f.__closure__[0].cell_contents =", f.__closure__[0].cell_contents) print("f.__closure__[1].cell_contents =", f.__closure__[1].cell_contents) 【出力例】 1 2 3 f.__closure__ = (<cell at 0x~: list object at 0x~>, <cell at 0x~: list object at 0x~>) f.__closure__[0].cell_contents = [1, 2, 3] f.__closure__[1].cell_contents = [1, 4, 9] 4 f.__closure__[0].cell_contents = [1, 2, 3, 4] f.__closure__[1].cell_contents = [1, 4, 9, 16] return【関数の戻り値】3.8メモ ( 複数の戻り値 複数の戻り値の代入 ) 構文 例 メモ関数・メソッドの戻り値を記述 複数の戻り値の指定が可能 (tuple【タプル型】のパック・アンパック 参照)戻り値の指定:タプルのパック戻り値の取得:タプルのアンパック list【リスト型】・tuple【タプル型】等をアンパックで展開時に、 タプルのカッコは省略可 3.8 〔 例 〕 複数の戻り値の代入変数 戻り値の tuple【タプル型】 を変数指定のタプルに代入 (カッコの省略可) 変数の個数に過不足があると ValueError 例外 前にアスタリスク付きの変数 (1個のみ指定可) を指定すると、過分の戻り値が list【リスト型】 で設定 関連 def【関数定義】 yield【ジェネレータ関数・一時停止】 外部リンク Python 言語リファレンスreturn 文 構文 return [戻り値 (複数:カンマ区切り)[,]] 戻り値 単一:任意 複数:タプル (tuple【タプル型】 参照) 省略:None ※:末尾のカンマは無視 (空の値等はなし) 例 def func_0(): return def func_1(p1): return p1*p1 def func_3(p1): return p1, p1*p1, p1*p1*p1 print(func_0()) # 出力:None print(func_1(2)) # 出力:4 r1 = func_3(2) print(r1) # 出力:(2, 4, 8) (r1, r2, r3) = func_3(2) print(r1, r2, r3) # 出力:2 4 8 r1, r2, r3 = func_3(2) print(r1, r2, r3) # 出力:2 4 8 #r1, r2 = func_3(2) # ValueError 例外 #r1, r2, r3, r4 = func_3(2) # ValueError 例外 r1, *r2 = func_3(2) print(r1, r2) # 出力:2 [4, 8] *r1, r2 = func_3(2) print(r1, r2) # 出力:[2, 4] 8 *r1, = func_3(2) print(r1) # 出力:[2, 4, 8] r1, r2, r3, *r4 = func_3(2) print(r1, r2, r3, r4) # 出力:2 4 8 [] # アンパック指定 def func_return_3_7(): lst = [1, 2, 3] tpl = (11, 12, 13) return (*lst, *tpl) # Python 3.8 def func_return_3_8(): lst = [1, 2, 3] tpl = (11, 12, 13) return *lst, *tpl x = func_return_3_7() print(x) # 出力:(1, 2, 3, 11, 12, 13) # Python 3.8 x = func_return_3_8() print(x) # 出力:(1, 2, 3, 11, 12, 13) lambda【ラムダ式 (無名関数)】メモ 構文 例 メモラムダ式で無名関数を記述 式のみ指定可 (文は不可)三項演算子は可 (参照:if-elif-else【条件分岐・三項演算子】) アノテーションの指定は不可 関数の引数に簡易関数を指定する場合に有用 無名のまま使用することを推奨 (PEP 8 -- Style Guide for Python Code: Programming Recommendations) 関連 def【関数定義】 Python 言語リファレンスラムダ (lambda) Python よくある質問プログラミング FAQ:ループの中で異なる値で定義されたラムダ式が、同じ値を返すのはなぜですか?デザインと歴史 FAQ:なぜラムダ式は文を含むことができないのですか?構文 lambda [引数 (複数:カンマ区切り)] : 返却値 (式) 引数def【関数定義】を参照 (但し、アノテーション指定は不可) 例 l = ["a_D", "A_C", "b_B", "B_A"] print(l) # 通常ソート print(sorted(l)) # 最後の文字順 print(sorted(l, key=lambda s: s[len(s) - 1])) 【出力例】 ['a_D', 'A_C', 'b_B', 'B_A'] ['A_C', 'B_A', 'a_D', 'b_B'] ['B_A', 'b_B', 'A_C', 'a_D'] list1 = [1, 2, 3, 5, 8, 13] map2 = map(lambda x: "偶数" if (x % 2) == 0 else "奇数", list1) list2 = list(map2) for i in range(len(list1)): print(list1[i], list2[i]) 【出力例】 1 奇数 2 偶数 3 奇数 5 奇数 8 偶数 13 奇数