[Python-Dev] terminology for "free variables" in Python

2010-09-09 Thread Eli Bendersky
The execution model section of the Python reference manual defines free
variables as follows:

"If a variable is used in a code block but not defined there, it is
a free variable"

This makes sense and fits the academic definition. The documentation of the
symtable module supports this definition - it says about is_free(): "return
True if the symbol is referenced in its block but not assigned to".

However, it appears that in the CPython front-end source code (in particular
the parts dealing with the symbol table), a free variables has a somewhat
stricter meaning. For example, in this chunk of code:

def some_func(myparam):
def internalfunc():
return cc * myparam

CPython infers that in 'internalfunc', while 'myparam' is free, 'cc' is
global because 'cc' isn't bound in the enclosing scope, although according
to the definitions stated above, both should be considered free. The
bytecode generated for loading cc and myparam is different, of course.

Is there a (however slight) inconsistency of terms here, or is it my
misunderstanding?

Thanks in advance,
Eli
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] terminology for "free variables" in Python

2010-09-09 Thread Guido van Rossum
On Thu, Sep 9, 2010 at 9:43 AM, Eli Bendersky  wrote:
> The execution model section of the Python reference manual defines free
> variables as follows:
>
>     "If a variable is used in a code block but not defined there, it is
> a free variable"
>
> This makes sense and fits the academic definition. The documentation of the
> symtable module supports this definition - it says about is_free(): "return
> True if the symbol is referenced in its block but not assigned to".
>
> However, it appears that in the CPython front-end source code (in particular
> the parts dealing with the symbol table), a free variables has a somewhat
> stricter meaning. For example, in this chunk of code:
>
> def some_func(myparam):
>     def internalfunc():
>     return cc * myparam
>
> CPython infers that in 'internalfunc', while 'myparam' is free, 'cc' is

What exactly do you mean by "infers" ? How do you know that it infers
that? How does it matter for your understanding of the code?

> global because 'cc' isn't bound in the enclosing scope, although according
> to the definitions stated above, both should be considered free. The
> bytecode generated for loading cc and myparam is different, of course.
>
> Is there a (however slight) inconsistency of terms here, or is it my
> misunderstanding?

That remains to be seen (please answer the questions above for a
better understanding of your question).

Maybe this helps though: global variables are a subset of free
variables, and they are treated different for various reasons (some
historic, some having to do with optimizations in the code -- I think
you saw the latter in the bytecode).

-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] terminology for "free variables" in Python

2010-09-09 Thread Nick Coghlan
On Fri, Sep 10, 2010 at 2:43 AM, Eli Bendersky  wrote:
> def some_func(myparam):
>     def internalfunc():
>     return cc * myparam
>
> CPython infers that in 'internalfunc', while 'myparam' is free, 'cc' is
> global because 'cc' isn't bound in the enclosing scope, although according
> to the definitions stated above, both should be considered free. The
> bytecode generated for loading cc and myparam is different, of course.
>
> Is there a (however slight) inconsistency of terms here, or is it my
> misunderstanding?

There's a slight inconsistency. The names a code object explicitly
calls out as free variables (i.e. references to cells in outer scopes)
are only a subset of the full set of free variables (every referenced
name that isn't a local variable or an attribute).

>>> from dis import show_code
>>> def outer():
...   x, y = 1, 2
...   def inner():
... print (x, y, a, b, c.e)
...   return inner
...
>>> f = outer()
>>> show_code(f)
Name:  inner
Filename:  
Argument count:0
Kw-only arguments: 0
Number of locals:  0
Stack size:6
Flags: OPTIMIZED, NEWLOCALS, NESTED
Constants:
   0: None
Names:
   0: print
   1: a
   2: b
   3: c
   4: e
Free variables:
   0: y
   1: x

a, b, and c are also free variables in the more general sense, but the
code object doesn't explicitly flag them as such since it doesn't need
to do anything special with them.

Cheers,
Nick.

-- 
Nick Coghlan   |   [email protected]   |   Brisbane, Australia
___
Python-Dev mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com