foo = baris syntactically correct, but you cannot tell whether variable bar is defined at that point or what kind of an object it refers to. What behavior do you have in the above simplest assignment ? It is that if variable bar is defined, a new local variable foo will reference the same object as bar. Something like this:
current_namespace["foo"] = reference_by_name("bar")This may be a trivial example, except for the behavior of the fictional reference_by_name function. Where does the language look up for a variable ? Like in the other languages that support procedural programming, Python procedures are natural namespace compartments. For example:
def foo(a): # begins foo's local namespaceEach procedure's individual namespace is in Python terms called "local namespace". Namespaces of nested procedures nest along with their frames, therefore a name inside of inner procedure may refer to the variable defined in an outer:
b = 1 # modifies foo's namespace
print(a) # fails because a is invisible here
print(b) # same
def foo():On the other hand, presence or absence of a name in a namespace is determined dynamically, at the moment of access, unlike static lexical scoping, which welcomes all sorts of awkward ambiguities like
b = 1
def bar():
print(b) # prints 1
bar()
def foo():and
b = 1
del b # would have deleted b from foo's namespace,
def bar(): # but could not be done, because this nested
print(b) # reference to b would hang (ouch !)
bar()
def foo(): def foo():Unless you want to maintain such ugly code, you should minimize using foreign variables in nested scopes, resorting to argument passing instead. Procedure arguments automatically become part of its local namespace and all locally accessed variables thus explicitly become local:
def bar(): def bar():
print(b) # prints 1 -VS- print(b) # fails because b is
b = 1 bar() # only almost there
bar() b = 1
def foo():Nevertheless, it is convenient to visualize the name resolution as scanning chain of nested scopes upwards:
b = 2
def bar(b): # explicitly local, no possible ambiguity
print b # prints 1
bar(1)
module.py:Note that in step 5 the containing module becomes an implicit embracing namespace which is the last chance to find the name. In Python this module namespace is called "global namespace". Finally, in addition to local and global namespaces, there is a "built-in namespace" which contains the language primitives that are not explicitly defined anywhere.
5) is b here ?
def foo():
4) is b here ?
def bar():
3) is b here ?
def biz():
2) is b here ?
def baz():
1) is b here ?
a = b
Therefore, even the simplest access to a variable is a lookup in three namespaces - local, global and built-in in that order.
To be continued...
4 comments:
Which version of Python are you using? For me the following code doesn't hang:
def foo():
b = 1
del b # would have deleted b from foo's namespace,
def bar(): # but could not be done, because this nested
print(b) # reference to b would hang (ouch !)
bar()
In fact it gives:
File "x.py", line 3
del b # would have deleted b from foo's namespace,
SyntaxError: can not delete variable 'b' referenced in nested scope
Which is what I would expect. This is using Python 2.4. Python doesn't hang if it cannot find a name, it simply raises NameError.
Ahem... I said that the _reference_ would hang, not the code. And yes, with my Python3k I have the same exception outcome as you.
Is there a cross-module name space in Python? At least, can I have a true reference to the other module's variable?
If I import another module, I can read from and write to its variables prefixed with the module name. But creating a reference to the other module's variable will expose unexpected copy-on-write semantics.
a.py:
v = 1
b.py:
import a
print a.v # 1
w = a.v
w = 2
print a.v # 1
My mistake. The cross-module references are no different from the module's own references. My confusion raised from misunderstanding of Python variables. They always return a reference to their content and will re-seat to the right-hand-value's reference, unlike C++ references.
Post a Comment