近日寫代碼又遇到兩個 Python 的坑,覺得值得記錄。
遞歸傳參問題
Python 裏傳參的實現是 assignment,但由於 Python 裏都是對象,除了幾個基本類型,assignment 基本都是引用的賦值,因此在遞歸裏,你傳的參數很可能就被下一層修改掉,例如:
def some_func(A):
# do your routines
some_func(A)
如果這個A
是個 mutable 的對象,而你的函數裏對A
有修改,那每一層遞歸都是修改同一個對象A
。
我是在寫一個解數獨的程序時發現這個問題的。這個程序裏有將 Numpy ndarray
作爲遞歸函數的參數,因此它在遞歸過程中被各種修改,完全亂了套。最後把調用遞歸傳入A
的地方換成A.copy()
就解決了問題。
浮點計算精度問題
這個問題本應是幾乎所有編程語言的問題,因爲計算機不能精確表示大多數浮點數,例如經典的0.1 + 0.2 != 0.3
。但這個問題在 Python 裏其實可以得到解決,就是使用 fraction 模塊。我們將所有有理浮點數都表示爲分數,就能完全保證計算過程中精度不會丟失。
# 使用 float 會丟失精度
>>> x = 0.1
>>> x == x * 3 / 3
False
# 使用 Fraction 則不會
>>> from fraction import Fraction
>>> x = Fraction('0.1')
>>> x == x * 3 / 3
True
注意,這裏是Fraction('0.1')
而不是Fraction(0.1)
,後者還是丟失精度的,因爲0.1
這個字面量在 Python 裏本身就不是準確的0.1,所以只能用字符串。
(本文完)