前回の投稿からの続きです。
デコレータによって、 いろいろと技巧的なことができるようになります。
Indent
Indentデコレータは、インデントレベルを保持するためにクラス内で定義され、メンバ関数をデコレートします。
また、デコレータは多段に適用できます、その場合、順番が変わると挙動が変わるので注意が必要です。
作為的で長くなってしまいましたが、「メンバ関数をデコレートする」手法と「多段にデコレートする」手法を合わせて例示します。
from functools import wraps
# ////////////////////////////////////////////////////////
# =================================================
class Indenter:
INDENT_WIDTH = 4
# ================================================
def __init__(self, *args, **kwds):
self.__dict__.update(kwds)
self.IndentLevel = 0
# ================================================
# -----------------------------------------------------------------------------
def inc(self):
self.IndentLevel += 1
return self.IndentLevel
# -----------------------------------------------------------------------------
def dec(self):
self.IndentLevel -= 1
return self.IndentLevel
# ================================================
# decorator Indent
def indent(a_Func):
@wraps(a_Func)
def wrapper(self, *args): # wrapperはメンバ関数になるのでself引数が必要
print(' ' * Indenter.INDENT_WIDTH * self.IndentLevel, end='')
a_Func(self, *args)
return wrapper
# ================================================
# decorator Kool
def kool(a_Func):
@wraps(a_Func)
def wrapper(self, *args): # wrapperはメンバ関数になるのでself引数が必要
print('KOOL! ', end='')
a_Func(self, *args)
return wrapper
# ================================================
@indent
def writeI(self, *args):
print(*args)
# ================================================
@kool
def writeK(self, *args):
print(*args)
# ================================================
@indent
@kool
def writeIK(self, *args):
print(*args)
# ================================================
@kool
@indent
def writeKI(self, *args):
print(*args)
print('\n... Indent')
i = Indenter()
i.writeI('A')
i.inc()
i.writeI('B')
i.inc()
i.writeI('C')
i.inc()
i.writeI('D')
i.dec()
i.dec()
i.dec()
i.writeI('A')
... Indent
A
B
C
D
A
print('\n... Kool')
i = Indenter()
i.writeK('A')
i.inc()
i.writeK('B')
i.inc()
i.writeK('C')
i.inc()
i.writeK('D')
i.dec()
i.dec()
i.dec()
i.writeK('A')
... Kool
KOOL! A
KOOL! B
KOOL! C
KOOL! D
KOOL! A
print('\n... Indent Kool')
i = Indenter()
i.writeIK('A')
i.inc()
i.writeIK('B')
i.inc()
i.writeIK('C')
i.inc()
i.writeIK('D')
i.dec()
i.dec()
i.dec()
i.writeIK('A')
... Indent Kool
KOOL! A
KOOL! B
KOOL! C
KOOL! D
KOOL! A
print('\n... Kool Indent')
i = Indenter()
i.writeKI('A')
i.inc()
i.writeKI('B')
i.inc()
i.writeKI('C')
i.inc()
i.writeKI('D')
i.dec()
i.dec()
i.dec()
i.writeKI('A')
... Kool Indent
KOOL! A
KOOL! B
KOOL! C
KOOL! D
KOOL! A
Choice
下記は与えられた複数のリストから値を選んで、重複のないリストを作り、関数に渡し、 その結果のリストを構築する、choiceデコレータです。
from functools import wraps
# ================================================
def choice(a_Func):
# --------------------------------------------------------------------------
def loop(*args):
if len(args) is 0:
return []
if len(args[1:]) is 0:
return [[i] for i in args[0]]
return [[i] + j for i in args[0] for j in loop(*args[1:])]
# --------------------------------------------------------------------------
@wraps(a_Func)
def wrapper(*args):
# mapに渡すために、lambdaでargsを展開してます
return [i for i in map((lambda args: a_Func(*args)), loop(*args))]
return wrapper
# ================================================
# tupleに包む
@choice
def hoge(*args):
return tuple(args)
hoge((1,2), (3,4))
... [(1, 3), (1, 4), (2, 3), (2, 4)]
# ================================================
# 合計する
@choice
def fuga(*args):
return sum(args)
fuga((1,2), (3,4))
... [4, 5, 5, 6]
# ================================================
# 文字列にして連結
@choice
def var(*args):
l_Return = ''
for i in args:
l_Return += str(i)
l_Return += ', '
return l_Return
var((1,2,3), ('A', 'B', 'C'), ('a', 'b', 'c'))
...
['1, A, a, ', '1, A, b, ', '1, A, c, ', '1, B, a, ', '1, B, b, ', '1, B, c, ', '1, C, a, ', '1, C, b, ', '1, C, c, ',
'2, A, a, ', '2, A, b, ', '2, A, c, ', '2, B, a, ', '2, B, b, ', '2, B, c, ', '2, C, a, ', '2, C, b, ', '2, C, c, ',
'3, A, a, ', '3, A, b, ', '3, A, c, ', '3, B, a, ', '3, B, b, ', '3, B, c, ', '3, C, a, ', '3, C, b, ', '3, C, c, ']
ひと通り、Pythonのデコレータについて、でした。
0 件のコメント:
コメントを投稿