ホーム > カテゴリ > Python・人工知能・Django >

ラムダ式/内包表記/ジェネレータ関数/yield /*args/**kwargs/デコレータ [Pythonの基本]

Python/TensorFlowの使い方(目次)

目次

1. ラムダ式
2. リスト内包表記
3. ディクショナリ内包表記
4. set内包表記
5. ジェネレータ関数とyield
6. ジェネレータ式
7. *args と **kwargs
8. デコレータ

※サンプルコードの「---」以下は出力結果です。

1. ラムダ式

lambda 引数 : 式

function = (lambda s : s + "モンテ")
function("プチ")
---
プチモンテ

1-1. map(マッピング/値の編集)

map(function, iterable, ...)
iterableをfunctionで演算する「イテレータ」を返す。

lst= [1,2,3]
list(map(lambda i : i + 5, lst))
---
[6, 7, 8]

mapの戻り値のイテレータは次のようになりますので、list()でイテレータをリストに変換しています。

<map at 0x1a00b475898>

1-2. filter(フィルタリング/絞込み)

SQLで言うとWHEREと同様です。

filter(function, iterable)
iterableをfunctionで絞り込む「イテレータ」を返す。

次は1-10の中で2で割り切れる数値をリストで返しています。

list(filter(lambda i : i % 2 == 0 , range(1, 11)))
---
[2, 4, 6, 8, 10]

filterの戻り値のイテレータは次のようになりますので、list()でイテレータをリストに変換しています。

<filter at 0x1a00b3bf978>

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}





関連記事



公開日:2018年07月01日 最終更新日:2018年08月24日
記事NO:02687