Python为什么我没有定义错误?

时间:2017-09-12 20:27:26

标签: python

当我在类代码块中使用任何类变量时,我没有定义错误。我该如何解决?

例如

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

感谢。

2 个答案:

答案 0 :(得分:4)

您的类变量已在A命名空间中。

所以你必须这样做:

__no_hidden_number__ = __hidden_number__ + 4

否则您尝试访问A.A并且它尚未存在。

为了说明我所说的内容,"工作" (但不是你想要的):

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

没有:

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

请注意,您应该避免使用尾随双下划线(__xxx__)来定义私有属性。它可以工作,但这通常保留给python特殊类成员(__class____file____eq__等...)。名称修改(使对象"私有")已经出现2个前导下划线。

答案 1 :(得分:2)

由于这可能有点不清楚(现有答案很好),让我补充一点:

class A:
    pass

is equivalent to

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

我们在类声明中编写的内容实际上是构建那个(此处为空)字典,并且在变量A被赋值之前发生。而且由于我们还没有 - 在类声明运行时命名空间层次结构中名称A的变量,A不可用。

该类存在,它还具有类型名称 'A',但尚未将其分配给变量A

class A: pass - 版本和显式type调用之间的区别是语法糖:使用class时,嵌套在类中的所有内容都会自动命名为类字典。

这就是为什么这样做的原因:

class A:
   var = 1
   var2 = var + 1

但是正如我们上面所看到的,最终将保存我们的新类的局部变量A仅在类声明已被评估之后才被分配,因此在其中不可用。

如果我们反汇编一个类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  
由于代码对象必须返回值,因此会自动添加

1922。我们可以忽略这些例子。

这里还发生了什么?

  • 0:将字符串'A'推入堆栈。这将成为类的名称(type()的第一个参数)。
  • 3:推送一个空元组,即父类列表
  • 6:加载类声明的代码对象。
  • 912运行类声明代码对象。这就是例如做我们的(类)变量赋值。它返回类字典。
  • 15将类构建到堆栈中。这相当于type('A', (), class_dict),其中参数恰好是此时堆栈上的值。

最后:

  • 16将新创建的类存储在名为A的本地名称空间中。

正如我们所看到的,在将类分配给变量12A)之前,将运行类声明(16)。

请注意,Python 3中的反汇编是不同的,因为python是一个特殊的内置class builder function

是的,这是一个太长的答案; - )。