作者huggie (huggie)
看板Python
标题Re: [问题] 关於class 内变数的问题
时间Thu Feb 5 14:01:32 2009
※ 引述《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)