perfect python section5

21
パーフェクトPython 5章 関数 1 13918日水曜日

Upload: satoooooooooooo

Post on 26-Jun-2015

192 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Perfect python section5

パーフェクトPython5章 関数

113年9月18日水曜日

Page 2: Perfect python section5

関数の定義def sample(arg1, arg2): print(“こんにちわ!”, arg1, arg2)

sample()

def neet(): # 何もしない関数 pass

def one_line(): return “1行!” # 1行でも書ける!

213年9月18日水曜日

Page 3: Perfect python section5

引数の指定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日水曜日

Page 4: Perfect python section5

デフォルト引数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日水曜日

Page 5: Perfect python section5

デフォルト引数# 回避策(本文中に乗ってたもの)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日水曜日

Page 6: Perfect python section5

可変長引数

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日水曜日

Page 7: Perfect python section5

可変長引数# 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日水曜日

Page 8: Perfect python section5

戻り値

def sample(arg1): return arg1 # arg1を返す

def sample(arg1): return arg1 # Noneを返す

813年9月18日水曜日

Page 9: Perfect python section5

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日水曜日

Page 10: Perfect python section5

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日水曜日

Page 11: Perfect python section5

ジェネレータ関数# 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日水曜日

Page 12: Perfect python section5

ジェネレータ関数# 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日水曜日

Page 13: Perfect python section5

ジェネレータ関数# 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日水曜日

Page 14: Perfect python section5

ジェネレータ関数# 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日水曜日

Page 15: Perfect python section5

ジェネレータ関数# サブジェネレータ# 単純に値を返すだけならこれで良いが...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日水曜日

Page 16: Perfect python section5

ジェネレータ関数# 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日水曜日

Page 17: Perfect python section5

高階関数# 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日水曜日

Page 18: Perfect python section5

lambda式

# 無名関数。# ここではitemが引数(lambda 引数: 処理)という構文def pick_odd(seq): return filter(lambda item: item % 2 == 0, seq)

1813年9月18日水曜日

Page 19: Perfect python section5

関数デコレータ# ある関数の前後に簡単に処理を差し込める。# 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日水曜日

Page 20: Perfect python section5

ドキュメンテーション文字列

# 関数の先頭の文字列はヘルプ機能で参照できる# ドキュメントとなるdef sum(arg1, arg2): “”” 二つの引数をとり、和を返します。

キーワード引数: arg1 -- 加算の左項 arg2 -- 加算の右項 “””

2013年9月18日水曜日

Page 21: Perfect python section5

# 関数の定義部分に引数や戻り値の説明を文字や数字で書ける# 引数は「引数名:注釈式 [= デフォルト値]」# 戻り値は「-> 注釈式」で書くことができるdef sum(left: ‘左項’, right: ‘右項’ = 10) -> ‘和’: ...

関数アノテーション

2113年9月18日水曜日