简体   繁体   English

Python为什么会出现未定义的错误?

[英]Python Why am I getting not defined error?

when I use any class variable in class code blocks, I'm getting not defined error. 当我在类代码块中使用任何类变量时,出现未定义的错误。 how can I fix it ? 我该如何解决?

example

class A():
    __hidden_number__ = 5
    __no_hidden_number__ = A.__hidden_number__ + 4 # to cause error. why ?

Thanks. 谢谢。

your class variable is already in A namespace. 您的类变量已经在A名称空间中。

So you just have to do: 因此,您只需要执行以下操作:

__no_hidden_number__ = __hidden_number__ + 4

else you're trying to access AA and it doesn't exist yet. 否则,您正在尝试访问AA ,但它尚不存在。

To illustrate what I'm stating, that "works" (but not what you want): 为了说明我在说什么,“有效”(但不是您想要的):

class A():
    class A():
        __hidden_number__ = 4
    __no_hidden_number__ = A.__hidden_number__ + 4
A()  # that works

that doesn't: 那不是:

class A():
    class B():
        __hidden_number__ = 4
    __no_hidden_number__ = A.__hidden_number__ + 4  # B.__... would've worked
A()  # beeep: NameError: name 'A' is not defined

note that you should avoid to define private attributes with trailing double underscore ( __xxx__ ). 请注意,您应避免使用尾随双下划线( __xxx__ )定义私有属性。 It works, but this is generally reserved for python special class members ( __class__ , __file__ , __eq__ , etc...). 它可以工作,但是通常保留给python特殊类成员( __class____file__ __class____file__ __eq__等)。 Name mangling (making the object "private") already occurs with 2 leading underscores. 名称修饰(使对象成为“私有”)已经发生了2个下划线。

Since this might be a little unclear (the existing answer is fine), let me add to that: 由于这可能还不清楚(现有答案很好),所以让我补充一点:

class A:
    pass

is equivalent to 相当于

A = type('A', (object,), {})

What we write inside the class declaration is essentially building that (here empty) dictionary and that happens before the variable A gets assigned. 我们在类声明中编写的内容本质上是在构建该字典(此处为空),并且在分配变量A 之前发生。 And since we have --not yet-- a variable of the name A in the namespace hierarchy while the class declaration runs, A isn't available. 而且由于在类声明运行时在命名空间层次结构中尚有一个尚未命名的变量A ,因此A不可用。

The class exists, it also has the type name 'A' , but it hasn't gotten assigned to the variable A , yet. 该类存在,它的类型名称 'A' ,但尚未将其分配给变量A

The difference between the class A: pass -version and the explicit type call is syntactic sugar: When using class , everything nested inside the class is automatically namespaced into the class dictionary. class A: pass -version和显式type调用之间的区别是语法糖:使用class ,嵌套在class中的所有内容都会自动命名为类字典。

This is why this works: 这就是为什么这样做的原因:

class A:
   var = 1
   var2 = var + 1

But as we can see above, the local variable A that will finally hold our new class is assigned only after the class declaration has already been evaluated and thus isn't available inside of it. 但是正如我们在上面看到的那样,只有在对类声明进行了评估之后,才分配最终将容纳我们的新类的局部变量A ,因此该变量A其内部不可用。

If we disassemble a class decl, we get: 如果我们反汇编一个class decl,我们将得到:

  import codeop, dis
  dis.disassemble(codeop.compile_command('class A:\r\n    pass'))

1           0 LOAD_CONST               0 ('A')
            3 LOAD_CONST               3 (())
            6 LOAD_CONST               1 (<code object A at 0x80076ff30, file "<input>", line 1>)
            9 MAKE_FUNCTION            0
           12 CALL_FUNCTION            0
           15 BUILD_CLASS         
           16 STORE_NAME               0 (A)
           19 LOAD_CONST               2 (None)
           22 RETURN_VALUE  

19 and 22 are added automatically, since code objects must return a value. 由于代码对象必须返回一个值,因此会自动添加1922 We can ignore those for our example. 对于我们的示例,我们可以忽略它们。

What else is happening here? 这里还发生了什么?

  • 0 : pushes the string 'A' onto the stack. 0 :将字符串'A'入堆栈。 This will become the name of the class (the first argument to type() ). 这将成为类的名称( type()的第一个参数)。
  • 3 : pushes an empty tuple, the list of parent classes 3 :推送一个空的元组,父类列表
  • 6 : Loads the code object for the class declaration. 6 :加载用于类声明的代码对象。
  • 9 and 12 run the class declaration code object. 912运行类声明代码对象。 This is what eg does our (class) variable assignments. 例如,这就是我们的(类)变量分配。 It returns the class dictionary. 它返回类字典。
  • 15 builds the class onto the stack. 15将类构建到堆栈上。 This is equivalent to type('A', (), class_dict) , where the parameters are exactly the values on the stack at this point. 这等效于type('A', (), class_dict) ,其中参数恰好是此时堆栈上的值。

And finally: 最后:

  • 16 stores the freshly created class into the local namespace under the name A . 16将新创建的类以名称A存储到本地名称空间中。

As we can see, the class declaration is run ( 12 ), before the class is assigned to its variable A ( 16 ). 如我们所见,在将类分配给变量A16 )之前,运行类声明( 12 )。

Note that the disassembly is different in Python 3, because python as a special builtin class builder function . 请注意,反汇编在Python 3中有所不同,因为python作为特殊的内置类builder函数

And yes, this is far too long an answer ;-). 是的,答案太长了;-)。

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

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