編程語言裏的「值」與「物」
今日在 Hacker News 上看到對一篇文章的討論——Values and objects in programming languages(MacLennan,1982),想起之前用 Python 時落入的一個陷阱。當時爲了初始化一個由 list
組成的 list
,寫了類似下面的代碼:
>>> l = [[]] * 10
>>> print(l)
[[], [], [], [], [], [], [], [], [], []]
如我所料,我得到了一個由十個空 list
組成的 list
。於是,我開始操作內層的 list
:
>>> l[0].append(0)
>>> l
[[0], [0], [0], [0], [0], [0], [0], [0], [0], [0]]
但我希望得到的結果是:
>>> l
[[0], [], [], [], [], [], [], [], [], []]
這個陷阱 Python 文檔也提到了1。看來掉進去的人不少。我並非不知 list
是 mutable 的,只是不自覺地就把「乘法」跟「值」聯繫起來了。
MacLennan 指出,「一切皆物」的語言需要經過仔細的設計。Python 大概就是這樣。我手邊的 Python 教材說:「Python 裏的所有數據——布爾值、整數、浮點數、字符串,甚至大型數據結構、函數以及程序——都是以_對象_(object)的形式存在的」2。此書指出:「Python 中的變量有一個非常重要的性質:它僅僅是一個名字。賦值操作並_不會實際複製_值,它只是爲數據對象_取個相關的名字_。名字是對對象的_引用_而不是對象_本身_。你可以把名字想像成貼在盒子上的標籤」3。隨後舉了下面這個例子(註釋是從原文的正文裏摘出來的):
>>> a = 7 # 將 7 賦值給名稱 a,這樣就成功創建了一個包含整數 7 的對象
>>> print(a) # 打印 a 的值
7
>>> b = a # 將 a 賦值給 b,這相當於給剛剛創建的對象又貼上了標籤
>>> print(b) # 打印 b 的值
7
若將 b = a
換成 b = 7
,是否又「創建了一個包含整數 7 的對象」?其實也可能還是「給剛剛創建的對象又貼上了標籤」。比較 id(a)
跟 id(b)
即可驗證。Python 文檔說:
All literals correspond to immutable data types, and hence the object’s identity is less important than its value. Multiple evaluations of literals with the same value (either the same occurrence in the program text or a different occurrence) may obtain the same object or a different object with the same value.4
id()
所反映的同一性屬於實現細節,用戶不用關心。可是由於「物」的類比,同一性難免會給思維造成負擔。
此書對 mutability 的解釋是:「你可以把不可變對象想像成一個透明但封閉的盒子:你可以看到裏面裝的數據,但是無法改變它。類似地,可變對象就像一個開着口的盒子,你不僅可以看到裏面的數據,還可以拿出來修改它」5。
這個類比也會遇到麻煩。Python 文檔說:
The value of an immutable container object that contains a reference to a mutable object can change when the latter’s value is changed; however the container is still considered immutable, because the collection of objects it contains cannot be changed. So, immutability is not strictly the same as having an unchangeable value, it is more subtle.6
沿用上述類比,恐怕只能勉強地說,盒子裏面裝的可以是鏡子。鏡子本身不會變,但照的東西可以變。
看來,「一切皆物」的編程語言不僅需要仔細的設計者,還需要仔細的學習者。「物」的類比有時並不簡單。(object 譯成「對象」總覺得意思不對。可是單音節的「物」又不大好用。)
Footnotes
-
https://docs.python.org/3/library/stdtypes.html#common-sequence-operations ↩
-
Lubanovic(2016),『Python 語言及其應用』,人民郵電出版社,第 13 頁。 ↩
-
Lubanovic(2016),第 15 頁。 ↩
-
https://docs.python.org/3/reference/expressions.html#literals ↩
-
Lubanovic(2016),第 13 頁。 ↩
-
https://docs.python.org/3/reference/datamodel.html#objects-values-and-types ↩