Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Perfect python section5

434 views

Published on

  • Login to see the comments

  • Be the first to like this

Perfect python section5

  1. 1. パーフェクトPython 5章 関数 113年9月18日水曜日
  2. 2. 関数の定義 def sample(arg1, arg2): print(“こんにちわ!”, arg1, arg2) sample() def neet(): # 何もしない関数 pass def one_line(): return “1行!” # 1行でも書ける! 213年9月18日水曜日
  3. 3. 引数の指定 def sample(arg1, arg2, arg3, arg4, arg5): print(arg1, arg2, arg3, arg4, arg5) # 以下、全て「1 2 3 4 5」を返す sample(1, 2, 3, 4, 5) sample(1, 2, arg4 = 4, arg3 = 3, arg2 = 2) # 位置指定のシーケンスは「*」、 # キーワード引数の辞書は「**」を付ける args = (2, 3) kwargs = {‘arg5’: 5, ‘arg4’: 4} sample(1, *args, **kwargs) 313年9月18日水曜日
  4. 4. デフォルト引数 def sample(arg1, arg2 = “好きな子に振られました...”): print(arg1, arg2) sample(’佐藤は、’) sample(’佐藤は、’, ‘それでも幸せです。’) # ミュータブルなオブジェクトをデフォルト値にする場合は注意 # デフォルト値は呼出毎ではなく関数生成時に一度だけ作成 def sample(arg1 = []): arg1.append(1) print(arg1) sample() # [1] sample() # [1, 1] sample() # [1, 1, 1] 413年9月18日水曜日
  5. 5. デフォルト引数 # 回避策(本文中に乗ってたもの) omit = object() def sample(arg1 = omit): if arg1 is omit: arg1 = [] arg1.append(1) # これでも問題なさそうですが...どうなんでしょう? def sample(arg1 = None): if arg1 is None: arg1 = [] arg1.append(1) 513年9月18日水曜日
  6. 6. 可変長引数 def sample(arg1, *args, **kwargs): print(arg1, args, kwargs) # -> 1 (2, 3, 4) {‘arg5’: 5, ‘arg6’: 6} # 引数2~4はシーケンスに、キーワード引数は辞書に格納される。 # キーワード引数は必ず最後に渡さなければならない。 sample(1, 2, 3, 4, arg5 = 5, arg6 = 6) 613年9月18日水曜日
  7. 7. 可変長引数 # python2.xでは可変長引数の後に # 他の引数を指定することはできなかったが # python3からキーワード引数を指定できるようになった。 def sample(arg1, *args, kwarg = ‘default’): print(arg1, args, kwarg) sample(1, 2, 3, 4, arg5 = 5) #下記の様に書けば、*以降の引数指定は # キーワード引数のみに限定される。 def sample(arg1, *, kwarg = ‘default’): print(arg1, args, kwarg) sample(1, 2) # エラー 713年9月18日水曜日
  8. 8. 戻り値 def sample(arg1): return arg1 # arg1を返す def sample(arg1): return arg1 # Noneを返す 813年9月18日水曜日
  9. 9. global宣言 smpl = ‘ウォールマリア’ def wall_maria(): smpl = ‘ウォールローゼ’ def wall_rose(): smpl = ‘ウォールシーナ’ def wall_sina(): global smpl return smpl return wall_sina() return wall_rose() wall_maria() # -> ‘ウォールマリア’ 913年9月18日水曜日
  10. 10. nonlocal宣言 smpl = ‘ウォールマリア’ def wall_maria(): smpl = ‘ウォールローゼ’ def wall_rose(): smpl = ‘ウォールシーナ’ def wall_sina(): nonlocal smpl return smpl return wall_sina() return wall_rose() wall_maria() # -> ‘ウォールシーナ’ # JavaScriptのスコープチェーンの様に近くから順に参照 1013年9月18日水曜日
  11. 11. ジェネレータ関数 # yield式を含み__next__()が呼ばれる度に実行される # 戻り値はyieldで指定された値 def fib(): a, b = 0, 1 # 初回一回実行 while True: yield a # ループの最初に実行 # !ループ処理終わるまでこの関数は中断 a, b = b, a + b # 1ループの最後に再開される items = [] # "ループ毎にvにyieldで指定された値が渡される for v in fib(): items.append(v) if len(items) > 10: break 1113年9月18日水曜日
  12. 12. ジェネレータ関数 # send()を使うと再会待ちのジェネレータに値を送れる def gen(step): val = 0 while True: val = val + step step = yield val g = gen(3) g.__next__() # 0 + 3 -> 3 g.send(10) # 3 + 10 -> 13 g.send(5) # 13 + 5 -> 18 # __next__を連続で呼び出すとエラーになるのは何故?? g = gen(3) g.__next__() g.__next__() # エラー 1213年9月18日水曜日
  13. 13. ジェネレータ関数 # throw()を使うと再会待ちジェネレータに例外を送れる def gen(): for i in range(10): yield i g = gen() for v in g: print(v) if i > 2: g.throw(ValueError(“Invalid value”)) 0 1 2 3 Traceback ~ ValueError: Invalid value 1313年9月18日水曜日
  14. 14. ジェネレータ関数 # close()を使うと再会待ちジェネレータを正常終了できる # GeneratorExit例外が送出されている def gen(): for i in range(10): yield i g = gen() for v in g: print(v) if i > 2: g.close() # ここでジェネレータを正常終了 1413年9月18日水曜日
  15. 15. ジェネレータ関数 # サブジェネレータ # 単純に値を返すだけならこれで良いが... def gen(): for i in sub_gen(): yield i # サブジェネレータのラッパーとして実装する場合はsend, # throwなどが使用されたときの事を考えると実装が複雑になる # そこでyield fromを使う(python3.3から) def gen(): yield from sub_gen() # send, throwなどが使われた場合はsub_genの物を呼ぶ 1513年9月18日水曜日
  16. 16. ジェネレータ関数 # yield fromで呼び出されるサブジェネレータは値を返せる。 # sub_genを直接使用する場合には戻り値は無視される。 def sub_gen(): yield 1 yield 2 return “これは戻り値です” def gen(): ret = yield from sub_gen() yield ret >>>for v in gen(): ... print(v) 1 2 これは戻り値です 1613年9月18日水曜日
  17. 17. 高階関数 # pythonでは関数もオブジェクトの一種。 # リストに格納したり引数に受け取って実行できる。 # 引数として取ったり戻り値として返す関数を高階関数と呼ぶ。 def is_odd(): return item % 2 == 1 def filter(pred, seq): ret = [] for item in seq: if pred(item): # 受け取った関数を実行 ret.append(item) return ret def pick_odd(seq): return filter(is_odd, seq) 1713年9月18日水曜日
  18. 18. lambda式 # 無名関数。 # ここではitemが引数(lambda 引数: 処理)という構文 def pick_odd(seq): return filter(lambda item: item % 2 == 0, seq) 1813年9月18日水曜日
  19. 19. 関数デコレータ # ある関数の前後に簡単に処理を差し込める。 # Dynamic Proxyみたいなもの? def shw_msg(f): def wrapper(): print(“function called”) return wrapper @show_msg def func(): .... @shw_msg # 複数の指定もできる @print_rslt # 一番下から順に適用される def func(): # func = shw_msg(print_rslt(func)) .... 1913年9月18日水曜日
  20. 20. ドキュメンテーション文字列 # 関数の先頭の文字列はヘルプ機能で参照できる # ドキュメントとなる def sum(arg1, arg2): “”” 二つの引数をとり、和を返します。 キーワード引数: arg1 -- 加算の左項 arg2 -- 加算の右項 “”” 2013年9月18日水曜日
  21. 21. # 関数の定義部分に引数や戻り値の説明を文字や数字で書ける # 引数は「引数名:注釈式 [= デフォルト値]」 # 戻り値は「-> 注釈式」で書くことができる def sum(left: ‘左項’, right: ‘右項’ = 10) -> ‘和’: ... 関数アノテーション 2113年9月18日水曜日

×