近日写代码又遇到两个 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,所以只能用字符串。
(本文完)