简体   繁体   中英

NameError: function definitions vs. class/dictionary definitions in python

Update

Thanks to @jwodder's reply below this is gradually becoming clearer to me.

Here is a simplified example that still confuses me:

This -- where a subsequently defined variable is referenced in a function definition -- runs fine:

#module.py
def function_scope():
    var = global_var
    return var

def print_global():
    var = function_scope()
    print var

global_var = "Here I am!"

#shell:
>>> from module import print_global
>>> print_global()
Here I am!

But this -- where the variable is referenced in a class definition -- fails:

#module.py
class ClassScope():
  var = global_var

def print_global():
  var = ClassScope.var
  print var

global_var = "Here I am!"

#shell
>>> from module import print_global
NameError: name 'global_var' is not defined

This implies that the class ClassScope() definition is "executed" at the time of the import. By contrast, the def function_scope() definition is "executed" when the function is called (ie, post-import, and therefore the function has access to module's full global scope).

  1. Am I thinking about this correctly in general? The concept of "executing" function/class definitions seems odd to me.
  2. Why this discrepancy between function definitions and class definitions?
  3. Is there a way to defer execution of the class definition, ie, to make it behave like a function, thereby giving it access to the entire module scope that would exist after a successful import?

Thanks again.

Original Question

I was originally trying to implement a function that accepts a class name and returns an object of that class. But along the way I realized that I don't have a good grasp of attribute scope . (Or maybe the issue is variable lifetime ?)

Why does the following work...

#module.py
def create_object(class_name):
    classes = {
        'ClassA':ClassA,
    }
    return classes[class_name]()

class ClassA(object):
    pass

#script.py
from module import create_object
obj = create_object('ClassA')

... but this fails?

#module.py
CLASSES = {
    'ClassA':ClassA,
}

def create_object(class_name):
    return CLASSES[class_name]()

class ClassA(object):
    pass 

#script.py
from module import create_object
obj = create_object('ClassA')

Here is the exception:

Traceback (most recent call last):
  File "script.py", line 2, in <module>
    from module import create_object
  File ".../module.py", line 3, in <module>
    'ClassA':ClassA,
NameError: name 'ClassA' is not defined

It looks like ClassA is not in scope as it's being referenced in the CLASSES dictionary in second example. But, if that's the case, why is it visible from within create_object() in the first example?

Any help in understanding this is much appreciated. Many thanks!

This has to do with the point at which name lookup happens, not scope. Python only tries to associate an identifier with an object or class when the code using that identifier is executed. In the first code snippet, the name ClassA in create_object is only assigned a meaning when create_object() is executed, by which time the class ClassA definition that creates ClassA has already been executed. In the second code snippet, you are trying to execute code that refers to ClassA before ClassA has even been defined, thus creating an error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM