Re: [問題] 關於class 內變數的問題

看板Python作者 (huggie)時間16年前 (2009/02/05 14:01), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串7/7 (看更多)
※ 引述《rockcen (杰)》之銘言: : clsee CA: : V1 = 'string' : def __init__(self): : self.V2 = 'string' : 想請問V2屬於class的實體變數吧? : 當object 被消滅時才會release : 想請問V1是什麼變數呢? : thanks! 我看了各位大大地回文之後覺得這個問題沒有真正的被回答到 以下是我推理的想法,有錯誤請指正 要想這個問題前,先把 static 變數的觀念拋開,因為你想得太複雜了。 如果月亮陰晴圓缺用簡單的光源被遮住就可以解釋,那就別想成是一隻 在太空會飛的狗把他吃掉了。這樣反而要記那些特例。 *** 所有 Python 的 definition 都是 executable statement *** 當我寫 a = 1 + 3 的時候,a 會得值 4 是因為 1 + 3 是個 statement。 1 + 3 有個傳回物件,物件是 integer 4。a 是一個 name/變數,這個 a 被 assign 了 integer 4 這個物件。 同理, def foo(): b = 1 + 3 def foo() 這邊也是個 statement,他定義了一個函式,內有 b = 1 + 3 這 個定義。回傳值是個函式,assign 給 foo 這個 name/變數。因此 foo 跟前 例的 a 並沒有什麼不同,只是一個是 integer 這個物件,一個是函式這個物 件。 注意 b = 1 + 3 只是這個函式的的定義,當下並不直接執行,只有實際呼叫的 時候,才被執行。因此 foo.b 並不存在。 你覺得 foo.b 很奇怪??試試看 foo.x = 'hello' 接下來後,foo() 既可以執行,print foo.x 又可以印出 hello,foo本來就是個 物件 dir(foo) 也一堆東西,多個 x 沒什麼奇怪的。 class CA: V1 = 'string' class CA 是個 statement,回傳值是個 class 物件,class 物件是個 container 一樣的東西(不知道這樣形容是否恰當),他是個可以有 has-a 關係的物件。 因此他包含了 V1 這個字串,你也可以用 CA.V1 來 access。也可以重設: CA.V1 = 'Hello' 也可以再多加設 CA.V2 = 'string2' 除了變數,也可以有函式: class CA: V1 = 'string' def foo(): # 注意沒有寫 self print 'hello foo' CA 的 foo 是存在的,不過 Python 不讓你呼叫 >>> CA.foo <unbound method A.foo> >>> CA.foo() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unbound method foo() must be called with A instance as first argument (got nothing instead) 改寫 class CA: V1 = 'string' def foo(self): self.V2 = 'string2' print 'hello foo' 此時 因為有 self 就需要是 instance 當作參數了。 所以我們 assign 一個 CA 的 instance,因為 CA 是一個 factory, 呼叫的時候會傳回 CA 的 instance object ca = CA() 什麼叫做 ca 是 CA 的 instance object? 上面那個 statement 會製造出 一個物件,這物件會承襲 CA 的變數以及CA 的函式。之後這個物件會被 assign 到 ca 這個 name 上。我說承襲是很單純的中文的意思,其實呢, ca.V1 有點像是個指標,指向了 CA.V1,ca.foo 也是一個指標,指向了 CA.foo 這個函式 當你說 ca.V1 的時候你其實是指向了 CA 裡面的 V1,因此如果 CA.V1 改變了,ca.V1自然也改變了: >>> ca = CA() >>> ca.V1 'string' >>> CA.V1 'string' >>> CA.V1 = 'changed' >>> ca.V1 'changed' 當你呼叫 ca.foo() 的時候呢,其實 Python 幫你 translate 成為 CA.foo(ca) 因此 self 就是 ca 這個物件。 self.V2 = 'string2' 的時候,它只是幫 ca 這個物件加了一個 V2,跟 CA 這個物件一點關係也沒有。 你可以事後幫 CA 多加一個函式: def bar(self): print 'in bar' CA.bar = bar 此時 CA.bar 存在,ca.bar() 就存在了,ca.bar 是一個像指標的東西,連結到 CA.bar 比較特別的是, 前面說 ca.V1 連結到 CA.V1,但假使你幫他重設,他就是一個屬於 ca 的物件了: ca.V1 = 'changed string' 這時候 ca.V1 就不指到 CA.V1 而是一個屬於 ca 自己的 V1。因此這時 ca.V1 跟 CA.V1 各自存在,值不同。 這概念就跟 def foo(self): self.V2 = 'string2' V2 是屬於 self,不屬於 CA 的 V2 一樣。 假使先前還宣告 ca2 = CA(),ca2 的 V1 仍然是指向 CA.V1,並沒有被影響。 總結, 1. Python所有的東西都是物件,CA是個物件,他的instance也是物件 2. 所有的物件都可以有他自己的變數。 3. create class instance 的時候,class instance 承襲自 class 的 物件以及函式,直到被 re-assign 為止。 原po的例子,V1就是一個CA的變數,V2就是他 intance 的變數,概念 其實很簡單。至於你要拿他來當Java static 用與否,那是使用的人的想法了。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.129.160.62 ※ 編輯: huggie 來自: 140.129.160.62 (02/05 14:02)
文章代碼(AID): #19Ye2zrj (Python)
文章代碼(AID): #19Ye2zrj (Python)