This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Inconsistent variable lookup
Type: behavior Stage:
Components: Interpreter Core Versions: Python 2.5
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: amaury.forgeotdarc, swarecki
Priority: normal Keywords:

Created on 2008-03-04 21:37 by swarecki, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (2)
msg63261 - (view) Author: Sylwester Warecki (swarecki) Date: 2008-03-04 21:37
Hi!

An example below shows how differently local variables are treated in
case of simple variables and classes. In case of objects the variable
refers to global object, in case of simple number - it refers to a local.

Example 2 shows worse case scenario. 
From the text alone of the test2() function it is impossible to forsee
its behavior (!). If there is no global variable 'a' then it crashes
although without declaration of 'a' as a global it runs fine with the
'+' operator on 'a'. However that will not be the case IF test3() is
invoked.
That is illogical.

Example 3 shows the worst case scenario.
functions z0 and z1 differ only by the variable name on the left side of
the equation. In first case a is understood as global in second as
local. What makes no sense is that the right side of equation does not
change, however its interpretation is based on the left side of the
equation. 

Example 4
This is an alteration of example 3 that shows the problem in full swing.
2 functions differ only by 2 last lines and yet they interpret the
variables in completely different way. In other words, adding a line to
end the code AFFECTS its beginning. That is least to say bizzaare.
..................

I tried to keep examples simple - hopefully that will help.

Regards,
    Sylwester

=================================================================

class cheat:
  def __init__( self ):
    self.q = 4

a = cheat( )
b = 3

def test():
  a.q = 22
  b   = 65
  print "test a=", a.q
  print "test b=", b
  
print "a=", a.q
print "b=", b

test()

print "a=", a.q
print "b=", b


=================================

example 2

class cheat2:
  def __init__( self ):
    self.q = 4
  def __add__( self, val ):
    self.q += val

a=cheat2()

def test2():
  c = a + 4
  print a.q

def test3():
  a += 4

test2()
test3()

===================================================
example 3

def z0():
  c = a + 2

def z1():
  a = a + 2

a = 10

z0()
z1()

=================================================================
example 4

def t1():
  print a
  x=a+2
  print x

An example below shows how differently local variables are treated in
case of simple variables and classes. In case of objects the variable
refers to global object, in case of simple number - it refers to a local.

Example 2 shows worse case scenario. 
From the text alone of the test2() function it is impossible to forsee
its behavior (!). If there is no global variable 'a' then it crashes
although without declaration of 'a' as a global it runs fine with the
'+' operator on 'a'. However that will not be the case IF test3() is
invoked.
That is illogical.

Example 3 shows the worst case scenario.
functions z0 and z1 differ only by the variable name on the left side of
the equation. In first case a is understood as global in second as
local. What makes no sense is that the right side of equation does not
change, however its interpretation is based on the left side of the
equation. 

Example 4
This is an alteration of example 3 that shows the problem in full swing.
2 functions differ only by 2 last lines and yet they interpret the
variables in completely different way. In other words, adding a line to
end the code AFFECTS its beginning. That is least to say bizzaare.
..................

I tried to keep examples simple - hopefully that will help.

Regards,
    Sylwester

=================================================================

class cheat:
  def __init__( self ):
    self.q = 4

a = cheat( )
b = 3

def test():
  a.q = 22
  b   = 65
  print "test a=", a.q
  print "test b=", b
  
print "a=", a.q
print "b=", b

test()

print "a=", a.q
print "b=", b


=================================

example 2

class cheat2:
  def __init__( self ):
    self.q = 4
  def __add__( self, val ):
    self.q += val

a=cheat2()

def test2():
  c = a + 4
  print a.q

def test3():
  a += 4

test2()
test3()

===================================================
example 3

def z0():
  c = a + 2

def z1():
  a = a + 2 # crash will happen here

a = 10

z0()
z1()

=================================================================
example 4

def t1():
  print a
  x=a+2
  print x

def t2():
  print a  #crash will happen here
  x=a+2
  print x
  a=a+4
  print a

t1()
t2() # this one will crash!
msg63266 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2008-03-04 22:21
> ... adding a line to end the code AFFECTS its beginning ...

Exactly. Please see
http://docs.python.org/dev/reference/executionmodel.html
"""
If a name binding operation occurs anywhere within a code block, all
uses of the name within the block are treated as references to the
current block. This can lead to errors when a name is used within a
block before it is bound. This rule is subtle. Python lacks declarations
and allows name binding operations to occur anywhere within a code
block. The local variables of a code block can be determined by scanning
the entire text of the block for name binding operations.
"""

For more general discussions, see also:
http://www.python.org/doc/faq/programming/#what-are-the-rules-for-local-and-global-variables-in-python
http://docs.python.org/dev/tutorial/classes.html#python-scopes-and-name-spaces

In other words, this is one of the key features of the python language,
and I don't see how it could change.
History
Date User Action Args
2022-04-11 14:56:31adminsetgithub: 46490
2008-03-04 22:21:49amaury.forgeotdarcsetstatus: open -> closed
resolution: not a bug
messages: + msg63266
nosy: + amaury.forgeotdarc
2008-03-04 21:46:27benjamin.petersonsettype: behavior
2008-03-04 21:37:07swareckicreate