简体   繁体   English

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

[英]NameError: function definitions vs. class/dictionary definitions in python

Update 更新资料

Thanks to @jwodder's reply below this is gradually becoming clearer to me. 感谢@jwodder在下面的回复,这对我来说逐渐变得清晰起来。

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. 这意味着在导入时将“执行” class ClassScope()定义。 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). 相比之下,在def function_scope()时(即,后导入,因此该函数可以访问模块的整个全局范围),将“执行” def function_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. 看起来ClassA不在范围内,因为第二个示例在CLASSES词典中对其进行了引用。 But, if that's the case, why is it visible from within create_object() in the first example? 但是,如果是这种情况,为什么在第一个示例中可以在create_object()中看到它?

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. 当执行使用标识符的代码时,Python仅尝试将标识符与对象或类相关联。 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. 在第一个代码段,该名称ClassAcreate_object仅被分配一个时意思create_object()通过该时间被执行, class ClassA创建定义ClassA已经被执行。 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. 在第二代码片段,您要执行的是指代码ClassAClassA ,甚至被定义,从而创造一个错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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