[Python-Dev] terminology for "free variables" in Python
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
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
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
