baffled classes within a function namespace. Evaluation order.

A

Alastair Thompson

I am completely baffled by the behavior of this code with regards to the
evaluation order of namespaces when assigning the class attributes. Both
classes are nested within a function I called whywhywhy.

I assumed that example1 and example2 classes would look first at their own
namespace, then object, then the whywhywhy func namespace then global, and
maybe module. It seems this is not the case.

def whywhywhy(first, second, third):
def print_stuff():
print("func: first=", first)
print("func: second=", second)
print("func: third=", third)
print_stuff()

class example1(object):
print("1cls: first=", first)
print("1cls: second=", second)
print("1cls: third=", third)

second = second
foo = third

class example2(object):
print("2cls: first=", first)
print("2cls: second=", second)
print("2cls: third=", third)

second = second
third = third

def second():
pass

whywhywhy(1,2,3)


The code above produces the following output
"""
func: first= 1
func: second= 2
func: third= 3
1cls: first= 1
1cls: second= <function second at 0xc6d380>
1cls: third= 3
2cls: first= 1
2cls: second= <function second at 0xc6d380>
Traceback (most recent call last):
File "error.py", line 29, in <module>
whywhywhy(1,2,3)
File "error.py", line 18, in whywhywhy
class example2(object):
File "error.py", line 21, in example2
print("2cls: third=", third)
NameError: name 'third' is not defined
"""

In particular:

print_stuff behaves as I would expect
1cls: second #<--- Why does this look at the global namespace for second
and not the whywhywhy func namespace first.
2cls: second #<--- Why can this no longer find third, it surely hasn't hit
the line third=third

Thanks for any help you can provide. :)
Alastair
 
B

Bas

I am completely baffled by the behavior of this code with regards to the evaluation order of namespaces when assigning the class attributes.  Bothclasses are nested within a function I called whywhywhy.
[snip weird namespace problem]

Hi,

I am not a namespace expert, but I think the following example shows the same problem in an easier way without any classes, and gives a more helpful error message:

In [1]: a = 123
In [2]: def f():
...: print a
...: b = 456

In [3]: f()
123

In [4]: def g():
...: print a
...: a = 456

In [5]: g()
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
/home/xxx/<ipython-input-5-d65ffd94a45c> in <module>()
----> 1 g()

/home/xxx/<ipython-input-4-c304da696fc2> in g()
1 def g():
----> 2 print a
3 a = 456
4

UnboundLocalError: local variable 'a' referenced before assignment


My guess is that in f(), the compiler sees no definition of a, so it assumes is must come from the outer namespace. In g(), however, it sees on the second line that a is uses as an assignment target, so it makes the variable a local. When it is executed, it rightfully complains that the local variable is not yet defined. A smarter compiler might prevent this problem, but then again a smarter programmer would not have local and global variables with the same name.

In your example, something similar is probably happening, since you assign something to third inside example2, thereby making it 'local'. Since you are dealing with classes, the error message is probably not so clear (but whywhywhy would you define a class inside a function?) Does that make sense?

HTH,
Bas
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,742
Latest member
AshliMayer

Latest Threads

Top