NameError:python中的函数定义与类/字典定义

时间:2013-11-16 01:21:03

标签: python python-2.7

更新

感谢@jwodder在下面的回复,这对我来说逐渐变得清晰。

这是一个简单的例子,但仍让我感到困惑:

这 - 在函数定义中引用随后定义的变量 - 运行良好:

#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!

但是 - 在类定义中引用变量的地方 - 失败:

#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

这意味着class ClassScope()定义在导入时“执行”。相比之下,def function_scope()定义在调用函数时“执行”(即导入后,因此函数可以访问模块的完整全局范围)。

  1. 我是否正确地考虑过这个问题? “执行”函数/类定义的概念对我来说似乎很奇怪。
  2. 为什么函数定义和类定义之间存在差异?
  3. 是否有办法推迟类定义的执行,即使其行为类似于函数,从而使其能够访问成功导入后存在的整个模块范围?
  4. 再次感谢。

    原始问题

    我最初尝试实现一个接受类名并返回该类对象的函数。但在此过程中我意识到我没有很好地掌握属性范围。 (或者问题可能是可变寿命?)

    为什么以下工作......

    #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')
    

    ......但这失败了吗?

    #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')
    

    以下是例外:

    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
    

    看起来ClassA不在范围内,因为它在第二个示例中的CLASSES字典中被引用。但是,如果是这种情况,为什么在第一个例子中create_object()内可以看到它?

    非常感谢任何理解这一点的帮助。非常感谢!

1 个答案:

答案 0 :(得分:0)

这与名称查找发生的点有关,而不是范围。当执行使用该标识符的代码时,Python仅尝试将标识符与对象或类相关联。在第一个代码段中,ClassA中的名称create_object仅在执行create_object()时被赋予含义,此时创建class ClassA的{​​{1}}定义已被执行。在第二个代码段中,您尝试在ClassA被定义之前执行引用ClassA的代码,从而产生错误。