當我在類代碼塊中使用任何類變量時,我得到未定義的錯誤。我該如何解決它?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'。檢查我的答案並測試片段。 –