Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Python (http://www.velocityreviews.com/forums/f43-python.html)
-   -   problem with closures (http://www.velocityreviews.com/forums/t397078-problem-with-closures.html)

alain 12-06-2006 05:23 PM

problem with closures
 
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


Gerard Brunick 12-07-2006 01:39 PM

Re: problem with closures
 
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
>




All times are GMT. The time now is 01:54 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.