classification
Title: Doc for locals and vars
Type: Stage:
Components: Versions: Python 3.1, Python 3.2, Python 2.7, Python 2.6
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: georg.brandl Nosy List: georg.brandl, orsenthil, siona, terry.reedy
Priority: normal Keywords:

Created on 2009-09-16 22:54 by terry.reedy, last changed 2009-09-19 22:32 by terry.reedy. This issue is now closed.

Messages (10)
msg92728 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2009-09-16 22:54
Doc for locals(): after correctly stating
"Update and return a dictionary representing the current local symbol table.

Note
The contents of this dictionary should not be modified; changes may not
affect the values of local variables used by the interpreter."

current doc goes on to say
"Free variables are returned by locals() when it is called in a function
block. Modifications of free variables may not affect the values used by
the interpreter. Free variables are not returned in class blocks."

As best I can understand this, it is wrong and should be removed. Free
variables within a function block are global/nonlocal names and by my
experimentation with 3.1, (including lambda expressions) are NOT
returned by locals(). If it means something else, it needs a rewrite.

The doc for var() starts "Without arguments, return a dictionary
corresponding to the current local symbol table." I suggest augmenting
this with 'update and ' (to match locals doc) and '(same as locals())'
to make that fact clear (as it is with help(vars)), even though removing
the 'Free variables' stuff will help the latter clearer also. The result
would be

Without arguments, update and return a dictionary corresponding to the
current local symbol table (same as locals()).
msg92759 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2009-09-17 12:27
Free variables *are* returned by locals().  (Note that globals *aren't*
free variables.)  For example, try this:

def f():
  x = 1
  def g():
    print locals()
  g()
f()
msg92800 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2009-09-18 04:35
Except for the variable name and 3.1 print(), that is exactly what I
tested before posting:
>>> 
{}

Was 2.x different?

Anyway, from Wikipedia: "In computer programming, a free variable is a
variable referred to in a function that is not a local variable or an
argument of that function." (from page called 'Free variables in Lisp")
Globals qualify under that definition. It goes on to say "An upvalue is
a free variable that has been bound (closed over) with a closure." which
is what Python calls nonlocal or cell var.
msg92804 - (view) Author: Senthil Kumaran (orsenthil) * (Python committer) Date: 2009-09-18 06:01
On Fri, Sep 18, 2009 at 04:35:37AM +0000, Terry J. Reedy wrote:
> Was 2.x different?

Even in 2.x it returns 
{}

And I thought that was expected. Even I am confused by the free
variable explaination as you pointed out. Perhaps, Georg could explain
better?
msg92809 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2009-09-18 07:18
I'm sorry, I messed up the test.  When "x" is not used in g(), it's of
course *not* a free variable in g.  This is the correct test:

def f():
  x = 1
  def g():
    print x
    print locals()
  g()
f()
msg92845 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2009-09-18 21:02
OK. Same is true of vars() also. So I suggest that current locals()
entry be changed to

"Update and return a dictionary representing the current local symbol
table. In function blocks, this includes nonlocal names.

Note
The contents of this dictionary should not be modified; changes may not
affect the values of local (or nonlocal) variables used by the interpreter."

and vars() first sentence be simplified to "Without arguments, same as
locals()." to follow the DRY principle.
msg92847 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2009-09-18 21:22
Should be fixed now in r74930.  I kept "free variables" because this is
the correct term, while "nonlocals" clashes with the "nonlocal"
statement in 3.x.
msg92852 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2009-09-18 22:37
I disagree with calling only nonlocal variables but not module variables
'free'. As I quoted from Wikipedia, that restrictive definition is not
agree on by all at all.  From The Free On-line Dictionary of Computing,
"1. A variable referred to in a function, which is not an argument of
the function. In lambda-calculus, x is a bound variable in the term M =
\ x . T, and a free variable of T. We say x is bound in M and free in T.
If T contains a subterm \ x . U then x is rebound in this term. This
nested, inner binding of x is said to "shadow" the outer binding.
Occurrences of x in U are free occurrences of the new x.
Variables bound at the top level of a program are technically free
variables within the terms to which they are bound but are often treated
specially because they can be compiled as fixed addresses. Similarly, an
identifier bound to a recursive function is also technically a free
variable within its own body but is treated specially."

Python does not treat top-level or recursive function names specially in
the way meant above.

I used 'nonlocal' specifically because the behavior of locals() seemed
by my testing to be concordant with the behavior of the 'nonlocal'
statement, which rejects the globals that locals does not print.  What
do you mean by 'clash'?
msg92866 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2009-09-19 10:35
> I disagree with calling only nonlocal variables but not module variables
> 'free'. As I quoted from Wikipedia, that restrictive definition is not
> agree on by all at all.

But it is the definition that Python uses, at least in the code.  I
agree that the usage of "free variable" in the reference manual is
inconsistent; this should be fixed independently.

> Python does not treat top-level or recursive function names specially in
> the way meant above.

It does treat them differently: they are globals, not free variables.

> I used 'nonlocal' specifically because the behavior of locals() seemed
> by my testing to be concordant with the behavior of the 'nonlocal'
> statement, which rejects the globals that locals does not print.  What
> do you mean by 'clash'?

"nonlocal" variables could be mistaken as variables that are declared as
nonlocal by such a statement.
msg92879 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2009-09-19 22:32
My point was and is that global variables *are* free variables by the
definition I learned and that I quoted and that in the absence of an
'official' and consistent definition for the purpose of the manual,
(linked to from its usages) people can and probably will be confused as
I was. I will leave this at that.
History
Date User Action Args
2009-09-19 22:32:10terry.reedysetmessages: + msg92879
2009-09-19 10:35:08georg.brandlsetmessages: + msg92866
2009-09-18 22:37:50terry.reedysetmessages: + msg92852
2009-09-18 21:22:25georg.brandlsetstatus: open -> closed
resolution: fixed
messages: + msg92847
2009-09-18 21:02:44terry.reedysetmessages: + msg92845
2009-09-18 07:18:16georg.brandlsetmessages: + msg92809
2009-09-18 06:01:01orsenthilsetnosy: + orsenthil
messages: + msg92804
2009-09-18 04:35:35terry.reedysetmessages: + msg92800
2009-09-17 12:27:53georg.brandlsetassignee: georg.brandl
2009-09-17 12:27:45georg.brandlsetnosy: + georg.brandl
messages: + msg92759
2009-09-17 11:13:54sionasetnosy: + siona
2009-09-16 22:54:40terry.reedycreate