当我在类代码块中使用任何类变量时,我得到未定义的错误。我该如何解决它?Python为什么我没有定义错误?
例如
class A():
__hidden_number__ = 5
__no_hidden_number__ = A.__hidden_number__ + 4 # to cause error. why ?
感谢。
当我在类代码块中使用任何类变量时,我得到未定义的错误。我该如何解决它?Python为什么我没有定义错误?
例如
class A():
__hidden_number__ = 5
__no_hidden_number__ = A.__hidden_number__ + 4 # to cause error. why ?
感谢。
你的类变量已经在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个前导下划线出现。
由于这可能是一个有点不清楚(现有的答案是罚款),让我补充到:
class A:
pass
A = type('A', (object,), {})
我们写的类声明里面有什么本质上是建立(这里是空的)字典,并且发生之前变量A
被分配。而且,由于我们还没有 - 名称空间层次结构中名称为A
的变量,而类声明运行时,A
不可用。
的类存在,它也有类型名称'A'
,但目前还没有得到赋值给变量A
,但。
的class A: pass
-version和明确type
调用之间的区别是语法糖:使用class
,一切都嵌套在类中被自动命名空间到类字典。
这就是为什么这个工程:
class A:
var = 1
var2 = var + 1
但我们可以在上面看到,局部变量A
,将最终持有类的声明已经被评估后,才我们的新类被分配,因此ISN” t可用于其内部。
如果我们拆开一类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
和22
会自动添加,因为代码对象必须返回一个值。我们可以忽略这些例子。
这里还发生了什么?
0
:将字符串'A'
推到堆栈上。这将成为班级的名字(type()
的第一个参数)。3
:推一个空元组,母类的列表6
:加载类声明的代码对象。9
和12
运行类声明代码对象。这是例如做我们的(类)变量分配。它返回类字典。15
将该类构建到堆栈上。这相当于type('A',(), class_dict)
,其中参数恰好是堆栈中此时的值。最后:
16
店刚创建的类到名称A
下的局部命名空间。我们可以看到,在类声明运行(12
),前级分配给它的可变A
(16
)。
请注意,在Python 3中反汇编是不同的,因为python作为特殊的内建函数class builder function。
是的,这是一个太长的答案;-)。
现在我明白了。这只是因为它正在构建中而不能成为相同的“A”。所以我们都是对的。你的回答是我忽略的一个很好的附加组件。 –
@ Jean-FrançoisFabre我并不是想说你错了,但细节有点讨厌。 Python是一个堆栈机器,区分“堆栈中的类型对象”A''和“名称为'A的变量来保存该类型对象”在这里有所不同。 – dhke
尝试'__no_hidden_number__ = __hidden_number__ + 4' –
因为'A'尚未定义。 –
@ juanpa.arrivillaga nope。你在'A'范围内。你指的是'A.A'。检查我的答案并测试片段。 –