Pythonの基本-簡単に。 パート6.機能の高度な定義。

続きは、 こちらをご覧ください



このセクションでは、関数の定義についてさらに詳しく説明し、このプロセスのPython固有の機能をいくつか明らかにします。 たくさんの情報があるので、すべてを簡潔に述べようとします。



デフォルトオプション



関数のすべてのパラメーターに対して、デフォルト値を指定できます。これにより、より少ないパラメーターで関数を呼び出すことができます。 たとえば、サイトのユーザーを認証する機能があります。

 def login(username="anonymous", password=None): """ - """ pass #       #    login("root", "ujdyzysqgfhjkm") login("guest") login() #        , #       login(password="nobody@mail.com")
      
      







一般に、存在するパラメーターは左から右に比較され(名前が特に指定されていない限り)、残りはデフォルト値に置き換えられます(もちろん指定されている場合)。

この場合の重要な機能は、デフォルトでは、値が一度だけ計算され、関数が宣言されたときに関連付けられることです。 これから生じるすべての欠点は、例によって明確に示されます。

 def_val = 2 def our_func(val = def_val): print val our_func(4) #  4 our_func() #  2 –  - def_val = 12 our_func() #   2,   def_val   2   
      
      





これのより不快な結果。 リストを入力として受け取り、それを使って何かを実行し、それを出力する関数を宣言したいとします。 さらに、リストが指定されていない場合、デフォルトでは空です。

この「正面から」の試みは、希望どおりには機能しません。

 In [1]: def lister(lst = []): ...: lst.append([1, 2, 3]) ...: print lst ...: In [2]: lister() [[1, 2, 3]] In [3]: lister() [[1, 2, 3], [1, 2, 3]] In [4]: lister() [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
      
      





実際、ここでの問題は、変数lstが一度空のリストに関連付けられ、呼び出し間でその値が保持されることです。

この場合、次のように関数を説明するのが正しいでしょう(すべての教科書が推奨しているように):

 In [5]: def lister2(lst=None): ...: if lst is None: ...: lst=[] ...: lst.append([1, 2, 3]) ...: print lst ...: In [6]: lister2() [[1, 2, 3]] In [7]: lister2() [[1, 2, 3]] In [8]: lister2([4, 5, 6]) [4, 5, 6, [1, 2, 3]]
      
      





この関数は、最初から希望どおりに機能します。



位置とキーワードの引数。



多くの場合、不特定数のパラメーターを処理する関数を作成する必要があります。 たとえば、リスト項目の合計を計算する機能。

もちろん、すべての引数を型リストの1つのパラメーターとして渡すことはできますが、見た目が悪くなります。 そのため、Pythonでは位置引数と呼ばれる特別なメカニズムが発明されました。 以下に使用例を示します。

 In [9]: def list_sum(*args): ...: smm = 0 ...: for arg in args: ...: smm += arg ...: return smm ...: In [10]: list_sum(1, 2, 3) Out[10]: 6 In [11]: list_sum(1) Out[11]: 1 In [12]: list_sum() Out[12]: 0
      
      





この場合、すべてのパラメーターは、送信中の「シリアル番号」に従って引数リストに「パック」されます。

逆の操作も可能です。値のリストがあり、それらを関数パラメーターのリストとして渡したいとしましょう:

 In [14]: lst = [1, 10, 2] In [15]: list(range(*lst)) Out[15]: [1, 3, 5, 7, 9]
      
      





この例では、lstリストは「アンパック」され、範囲関数パラメーターに置き換えられました。つまり、呼び出しは類似しています。

 In [16]: list(range(1, 10, 2)) Out[16]: [1, 3, 5, 7, 9]
      
      





位置に加えて、いわゆるを使用できます。 キーワード引数。 明示的に名前を指定する必要があるという点で異なります。 以下に例を示します-データベースの挿入式を生成する関数(NB:この場合、最大最適化はそれ自体で終了として設定されませんでした)。

 def enquote1(in_str): """Quotes input string with single-quote""" in_str = in_str.replace("'", r"\'") return "'%s'" % in_str def enquote2(in_str): """Quotes input string with double-quote""" in_str = in_str.replace('"', r'\"') return '"%s"' % in_str def gen_insert(table, **kwargs): """Generates DB insert statement""" cols = [] vals = [] for col, val in kwargs.items(): cols.append(enquote2(col)) vals.append(enquote1(str(val))) cols = ", ".join(cols) vals = ", ".join(vals) return 'INSERT INTO "%s"(%s) VALUES(%s);' % ( table, cols, vals) print gen_insert("workers", name="John", age=21, salary=1500.0) params = {"name": "Mary", "age": 19, "salary": 1200.0} print gen_insert("workers", **params)
      
      





出力では、予想されたものが得られます。

 INSERT INTO "workers"("salary", "age", "name") VALUES('1500.0', '21', 'John'); INSERT INTO "workers"("salary", "age", "name") VALUES('1200.0', '19', 'Mary');
      
      





gen_insert関数の2番目の呼び出しに注意してください-この方法では、パラメーターの辞書のみを使用して関数を呼び出すことができます。 これはすべての機能に適用されます。 位置引数とキーワード引数のさまざまな組み合わせも可能です。



最後の例として、次の関数を検討してください。

 def logging(func, *args, **kwargs): res = func(*args, **kwargs) print 'calling %s, returned %r' % (func.__name__, res) return res def double(x): "Doubles a number" return 2*x print logging(double, 155)
      
      





これは、関数をデバッグする最も簡単な方法です。中間情報を表示するために、ある関数から別の関数への呼び出しを「ラップ」します。

今後の展望-Pythonには、この種の「ラッピング」関数をより便利に使用するデコレーターと呼ばれる非常に強力なツールがありますが、これについては後で詳しく説明します。



今日は以上です。 継続するには(鉱山または尊敬されるGerlionのいずれか)、私たちと一緒にいてください。



宿題



子関数が呼び出されるパラメーターの出力と、子関数で発生する可能性のある例外の処理をログ関数に追加して、ログ関数を変更します。



All Articles