Upload
satoooooooooooo
View
216
Download
0
Tags:
Embed Size (px)
Citation preview
パーフェクトPython5章 関数
113年9月18日水曜日
関数の定義def sample(arg1, arg2): print(“こんにちわ!”, arg1, arg2)
sample()
def neet(): # 何もしない関数 pass
def one_line(): return “1行!” # 1行でも書ける!
213年9月18日水曜日
引数の指定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日水曜日
デフォルト引数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日水曜日
デフォルト引数# 回避策(本文中に乗ってたもの)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日水曜日
可変長引数
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日水曜日
可変長引数# 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日水曜日
戻り値
def sample(arg1): return arg1 # arg1を返す
def sample(arg1): return arg1 # Noneを返す
813年9月18日水曜日
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日水曜日
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日水曜日
ジェネレータ関数# 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日水曜日
ジェネレータ関数# send()を使うと再会待ちのジェネレータに値を送れるdef gen(step): val = 0 while True: val = val + step step = yield val
g = gen(3)g.__next__() # 0 + 3 -> 3g.send(10) # 3 + 10 -> 13g.send(5) # 13 + 5 -> 18
# __next__を連続で呼び出すとエラーになるのは何故??g = gen(3)g.__next__()g.__next__() # エラー
1213年9月18日水曜日
ジェネレータ関数# 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”))
0123Traceback ~ ValueError: Invalid value
1313年9月18日水曜日
ジェネレータ関数# 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日水曜日
ジェネレータ関数# サブジェネレータ# 単純に値を返すだけならこれで良いが...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日水曜日
ジェネレータ関数# 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)12これは戻り値です
1613年9月18日水曜日
高階関数# 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日水曜日
lambda式
# 無名関数。# ここではitemが引数(lambda 引数: 処理)という構文def pick_odd(seq): return filter(lambda item: item % 2 == 0, seq)
1813年9月18日水曜日
関数デコレータ# ある関数の前後に簡単に処理を差し込める。# Dynamic Proxyみたいなもの?def shw_msg(f): def wrapper(): print(“function called”) return wrapper
@show_msgdef func(): ....
@shw_msg # 複数の指定もできる@print_rslt # 一番下から順に適用されるdef func(): # func = shw_msg(print_rslt(func)) ....
1913年9月18日水曜日
ドキュメンテーション文字列
# 関数の先頭の文字列はヘルプ機能で参照できる# ドキュメントとなるdef sum(arg1, arg2): “”” 二つの引数をとり、和を返します。
キーワード引数: arg1 -- 加算の左項 arg2 -- 加算の右項 “””
2013年9月18日水曜日
# 関数の定義部分に引数や戻り値の説明を文字や数字で書ける# 引数は「引数名:注釈式 [= デフォルト値]」# 戻り値は「-> 注釈式」で書くことができるdef sum(left: ‘左項’, right: ‘右項’ = 10) -> ‘和’: ...
関数アノテーション
2113年9月18日水曜日