problem with closures

Gerard Brunick gbrunick at andrew.cmu.edu
Thu Dec 7 08:39:26 EST 2006


I can't solve your problem, but I can at least explain why I think its 
hard.  foo doesn't have any closed over
variables.  Some of its locals have to live in cells, so that pre and 
post can see them in their closures.

 >>> foo.func_code.co_cellvars
('x', 'y')

Now the only way that I know of to get a local variable to be put in a 
cell, where you can then plug
it into a func_closure, it to write a function which a contains a 
function with a closure.  Moreover, this
requires that the function signatures really match to work.  Consider

 >>> def test(*arg, **args):
...     def inner():
...         print x
...     return inner
...
 >>> f = test(x=5)
 >>> f()
Traceback (most recent call last):
  File "<interactive input>", line 1, in ?
  File "<interactive input>", line 3, in inner
NameError: global name 'x' is not defined

Since x isn't a named argument of test, the compiler just assumes that 
its a global.
This means that your contract function is going to have to build a 
string and exec
to make the newf so its arguments match foo exactly.  Of course the 
compiler is
really finicky about exec, when there are free variables around, and I 
don't claim
to understand the rules.



alain wrote:
> Hi,
>
> I have a problem with closures.
> I am trying to implement yet another design by contract decorator which
> would look like the following:
> <pre>
> def contract(f):
> 	def newf(*args, **kw):
> 		import new
> 	        precondition =  new.function(f.func_code.co_consts[1],
> 							f.func_globals,'pre',
> 							f.func_defaults,
> 							f.func_closure)
> 		precondition()
> 		result=f(*args, **kw)
> 		postcondition=new.function(f.func_code.co_consts[2],globals())
> 		postcondition(result)
> 		return result
> 	return newf
> @contract
> def foo(x,y,g=2,z=1):
> 	def pre():
> 		assert x>1 and 0<y<100
> 	def post(result):
> 		assert result >0
> 	print 'main'
> 	return x+y+z*g
>
> print foo(2,5,4,69)
> <pre>
>
> The problem is that i get the following error message on line 7:
> TypeError: arg 5 (closure) must be tuple
>
> f.func_closure is indeed empty while
> f.func_code.co_consts[1].co_freevars is logically equal to ('x','y').
>
> Thanks for responding
>
> Alain
>




More information about the Python-list mailing list