ラムダ式/内包表記/ジェネレータ関数/yield /*args/**kwargs/デコレータ [Pythonの基本]
目次
1. ラムダ式
2. リスト内包表記
3. ディクショナリ内包表記
4. set内包表記
5. ジェネレータ関数とyield
6. ジェネレータ式
7. *args と **kwargs
8. デコレータ
※サンプルコードの「---」以下は出力結果です。
1. ラムダ式
function = (lambda s : s + "モンテ") function("プチ") --- プチモンテ
1-1. map(マッピング/値の編集)
iterableをfunctionで演算する「イテレータ」を返す。
lst= [1,2,3] list(map(lambda i : i + 5, lst)) --- [6, 7, 8]
mapの戻り値のイテレータは次のようになりますので、list()でイテレータをリストに変換しています。
1-2. filter(フィルタリング/絞込み)
SQLで言うとWHEREと同様です。
iterableをfunctionで絞り込む「イテレータ」を返す。
次は1-10の中で2で割り切れる数値をリストで返しています。
list(filter(lambda i : i % 2 == 0 , range(1, 11))) --- [2, 4, 6, 8, 10]
filterの戻り値のイテレータは次のようになりますので、list()でイテレータをリストに変換しています。
2. リスト内包表記
[元のコード]
lst = [] for i in range(1,6): lst.append(i * 2) lst --- [2, 4, 6, 8, 10]
[リスト内包表記]
[i * 2 for i in range(1,6)] --- [2, 4, 6, 8, 10]
2-1. if(フィルタリング/絞込み)
値を絞り込むときにはifを使用します。SQLのWHERE相当です。
次式は1-10の中が2で割り切れる数値をリストで返しています。
[i for i in range(1,11) if i % 2 == 0] --- [2, 4, 6, 8, 10]
3. ディクショナリ内包表記
dic = {'a':1, 'b':2, 'c':3} {key:val+1 for key, val in dic.items()} --- {'a': 2, 'b': 3, 'c': 4}
※ifで絞り込み可能です。
4. set内包表記
lst = ["red", "green", "blue"] {i.upper() for i in lst} --- {'BLUE', 'GREEN', 'RED'}
※ifで絞り込み可能です。
5. ジェネレータ関数とyield
ジェネレータ関数は「イテレータ」を返します。
実行時にyieldの行になると、その値を返し、その行でジェネレータ関数から抜け出します。そして、次の呼び出しで、その続きから始まります。
def myfunc(): yield 'red' yield 'green' yield 'blue' it = myfunc() for x in it: print(x,end=' ') --- red green blue
def myfunc(): yield 'red' yield 'green' yield 'blue' it = myfunc(); print(next(it), next(it), next(it)) --- red green blue
def myfunc(): for i in range(11): if i % 2 == 0: yield i it = myfunc() for i in it: print(i, end = ' ') --- 0 2 4 6 8 10
このジェネレータ関数のメリットとしては1回毎に実行するので、一時的なメモリ消費が抑えられます。
6. ジェネレータ式
リスト内包表記と似たような機能のジェネレータ式があります。リスト内包表記はリストを返しますが、ジェネレータ式はイテレータを返します。
it = (i*2 for i in range(1, 4)) for i in it: print(i, end = ' ') --- 2 4 6
it = (i*2 for i in range(1, 4)) print(next(it), next(it), next(it) ) --- 2 4 6
7. *args と **kwargs
*argsはタプル(tuple)。
def myfunc(*args): for i in args: print (i, end=' ') myfunc(1,2,3) --- 1 2 3
**kwargsは辞書(dict)
def myfunc(**kwargs): for key in kwargs: print (key, '=', kwargs[key]) myfunc(a = 1, b = 2, c = 3) --- a = 1 b = 2 c = 3
8. デコレータ
次のような高階関数(関数を変数で使用)のコードがあるとします。
def outer(func): # 内部関数の定義 def inner(*args): # ここでhello関数を実行する func(args[0] + 'モンテ') # 内部関数を実行する return inner def hello(msg): print(msg) newfunc = outer(hello) newfunc('プチ') --- プチモンテ
これにデコレータ(@)を使用すると次のようになります。
def outer(func): # 内部関数の定義 def inner(*args): # ここでhello関数を実行する func(args[0] + 'モンテ') # 内部関数を実行する return inner @outer def hello(msg): print(msg) hello('プチ') --- プチモンテ
次は少し複雑なタイプです。 ※定義と共に即時実行されます。
def outer(*args, **kwargs): def inner(func): func() print(args[0], kwargs.get('option')) return inner @outer('A', option=True) def myfunc1(): print('myfunc1', end=' ') @outer('B', option=False) def myfunc2(): print('myfunc2', end=' ') --- myfunc1 A True myfunc2 B False
更にゴニョゴニョしてみる。
def outer(*oargs, **okwargs): def center(func): def inner(*args, **kwargs): func(*args, **kwargs) print('*oargs={}, **okwargs={}'.format(oargs, okwargs)) return inner return center @outer('@outerの引数', option=True) def myfunc(*args, **kwargs): print('*args={}, **kwargs={}'.format(args, kwargs)) myfunc('myfuncの引数', flg=False) --- *args=('myfuncの引数',), **kwargs={'flg': False} *oargs=('@outerの引数',), **okwargs={'option': True}