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