クロージャで関数定義時の自分を囲むスコープの情報を記憶している
- そのため下記では定義した時点で与えた引数の情報を,関数実行時に与えなくても保持できる
1>>> def outer(x):
2... def inner():
3... print x
4... return inner
5>>> print1 = outer(1)
6>>> print2 = outer(2)
7>>> print1()
81
9>>> print2()
102
- デコレータ=関数を引数にとり,引き換えに新たな関数を返すcallable(*)
- 与えられた関数に,処理を追加した関数を返す
1>>> def outer(some_func):
2... def inner():
3... print "before some_func"
4... ret = some_func() #1
5... return ret + 1
6... return inner
7>>> def foo():
8... return 1
9>>> decorated = outer(foo) #2
10>>> decorated()
11before some_func
122
- 座標オブジェクトに対して計算処理を後付したい場合
1>>> class Coordinate(object):
2... def __init__(self, x, y):
3... self.x = x
4... self.y = y
5... def __repr__(self):
6... return "Coord: " + str(self.__dict__)
7>>> def add(a, b):
8... return Coordinate(a.x + b.x, a.y + b.y)
9>>> def sub(a, b):
10... return Coordinate(a.x - b.x, a.y - b.y)
11>>> one = Coordinate(100, 200)
12>>> two = Coordinate(300, 200)
13>>> add(one, two)
14Coord: {'y': 400, 'x': 400}
15
16>>> def wrapper(func):
17... def checker(a, b):
18... if a.x < 0 or a.y < 0:
19... a = Coordinate(a.x if a.x > 0 else 0, a.y if a.y > 0 else 0)
20... if b.x < 0 or b.y < 0:
21... b = Coordinate(b.x if b.x > 0 else 0, b.y if b.y > 0 else 0)
22... ret = func(a, b)
23... if ret.x < 0 or ret.y < 0:
24... ret = Coordinate(ret.x if ret.x > 0 else 0, ret.y if ret.y > 0 else 0)
25... return ret
26... return checker
27>>> add = wrapper(add)
28>>> sub = wrapper(sub)
29>>> sub(one, two)
30Coord: {'y': 0, 'x': 0}
31>>> add(one, three)
32Coord: {'y': 200, 'x': 100}
@
による糖衣構文
1def add(a, b):
2 return Coordinate(a.x + b.x, a.y + b.y)
3add = wrapper(add)
=
1@wrapper
2def add(a, b):
3 return Coordinate(a.x + b.x, a.y + b.y)
- loggerの例
1>>> def logger(func):
2... def inner(*args, **kwargs): #1
3... print "Arguments were: %s, %s" % (args, kwargs)
4... return func(*args, **kwargs) #2
5... return inner
6>>> @logger
7... def foo1(x, y=1):
8... return x * y
9>>> @logger
10... def foo2():
11... return 2
12>>> foo1(5, 4)
13Arguments were: (5, 4), {}
1420
15>>> foo1(1)
16Arguments were: (1,), {}
171
18>>> foo2()
19Arguments were: (), {}
202
Tagged: #Python