Re: [問題] 關於class 內變數的問題
※ 引述《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)
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 7 之 7 篇):
Python 近期熱門文章
PTT數位生活區 即時熱門文章