[python] closure


closure is often used as function factory, one example being:

>>> def maker(N):
...     def action(X):
...             return X ** N
...     return action
... 
>>> f = maker(2)
>>> f(3)
9

lambda version:

>>> def maker(N):
...     return lambda X: X ** N
... 
>>> f = maker(2)
>>> f(3)
9

the use of closure could extend the use of inner function outside its scope, in the example, the inner function action.

the detail of this state retention process: http://www.cnblogs.com/ChrisChen3121/p/3208119.html
how to read the output from dis.dis:
1. https://stackoverflow.com/questions/12673074/how-should-i-understand-the-output-of-dis-dis
2. http://www.goldsborough.me/python/low-level/2016/10/04/00-31-30-disassembling_python_bytecode/
3. https://docs.python.org/3.5/library/dis.html#python-bytecode-instructions

>>> def maker(N):
...     def action(X):
...             return X ** N
...     return action
... 
>>> maker.__code__
<code object maker at 0x7fe5104f2030, file "<stdin>", line 1>
>>> import dis
>>> dis.dis(maker.__code__)
  2           0 LOAD_CLOSURE             0 (N)
              3 BUILD_TUPLE              1
              6 LOAD_CONST               1 (<code object action at 0x7fe5186e39c0, file "<stdin>", line 2>)
              9 LOAD_CONST               2 ('maker.<locals>.action')
             12 MAKE_CLOSURE             0
             15 STORE_FAST               1 (action)

  4          18 LOAD_FAST                1 (action)
             21 RETURN_VALUE
>>> f = maker(2)
>>> f.__closure__
(<cell at 0x7fe518708318: int object at 0x7fe518674980>,)
>>> dir(f.__closure__[0])
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
>>> f.__closure__[0]
<cell at 0x7fe518708318: int object at 0x7fe518674980>
>>> f.__closure__[0].cell_contents
2

One thing should be cared is using loop to create nested functions inside a loop.

>>> def maker(N):
...     acts = []
...     for i in range(N):
...             acts.append(lambda X: X ** i)
...     return acts
... 
>>> flist = maker(3)
>>> for f in flist:
...     print(f(2))
... 
4
4
4

The reason is all the lambda functions reference the value bounded only when called - the value i is 2.
Use default argument to solve this

>>> def maker(N):
...     acts = []
...     for i in range(N):
...             acts.append(lambda X, i=i: X ** i)
...     return acts
... 
>>> flist = maker(3)
>>> for f in flist:
...     print(f(2))
... 
1
2
4

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值