Pythonでプログラムを書いていると、
Python はクロージャに対応していて、
クロージャが一番役に立つ場面がデコレータです。次の例では、
# coding: utf-8
from __future__ import print_function
import sys
def log(out=sys.stderr):
def decorator(func):
name = func.__name__
def decorated(*args, **kwargs):
### 外側の関数の変数 name, out を利用できる
print("%s start" % name, file=out)
func(*args, **kwargs)
print("%s end" % name, file=out)
return decorated
return decorator
@log(sys.stdout)
def foo(a, b):
print(a + b)
foo(1, 2)
foo start 3 foo end
Pythonのクロージャには、
def decorator(func):
name = func.__name__
called = 0 ### カウンタ
def decorated(*args, **kwargs):
called += 1 ### UnboundLocalError: local variable 'called' referenced before assignment
print("%s starts %d times" % (name, called), file=out)
func(*args, **kwargs)
print("%s ends %d times" % (name, called), file=out)
return decorated
$ python2.6 test2.py Traceback (most recent call last): File "test2.py", line 22, infoo(1, 2) File "test2.py", line 11, in decorated called += 1 UnboundLocalError: local variable 'called' referenced before assignment
Pythonでは、
このような場合、
called = [0] ### リストの最初の要素がカウンタ
def decorated(*args, **kwargs):
called[0] += 1 ### 変数ではなくリストの要素を更新
Python 3.
called = 0
def decorated(*args, **kwargs):
nonlocal called ### calledはローカル変数ではない
called += 1 ### O.K.
この制限は、