我正在考虑从Matlab转到Python/numpy进行数据分析和数值模拟。我已经使用Matlab(和SML-NJ)很多年了,在没有副作用的功能环境中非常舒服(除了I/O),但是对于Python中的副作用我有点不情愿。人们能分享他们最喜欢的关于副作用的窍门吗?如果可能的话,他们是如何避开这些问题的?例如,当我在Python中尝试以下代码时,我有点惊讶:
lofls = [[]] * 4 #an accident waiting to happen!
lofls[0].append(7) #not what I was expecting...
print lofls #gives [[7], [7], [7], [7]]
#instead, I should have done this (I think)
lofls = [[] for x in range(4)]
lofls[0].append(7) #only appends to the first list
print lofls #gives [[7], [], [], []]
提前谢谢
我最近在尝试消除对numpy的一个小依赖时,又偶然发现了这个问题(在python多年之后)。在
如果您来自matlab,您应该使用并信任
numpy
函数来处理单类型数组。与matplotlib一起,它们是一些非常方便的软件包,可以实现平滑过渡。在等等
将对同一个(可变)对象的引用与对不同对象的引用混淆起来确实是一个“问题”(所有非函数性语言都会遇到这种情况,即具有可变对象和引用的语言)。初学者Python代码中经常出现的一个错误是误用了一个可变的默认值,例如:
如果目的是让
addone
保持自己的状态(并将一个增长的列表返回给连续的调用方),则此代码可能是正确的,就像static
数据在C中可以工作一样;如果编码人员错误地假设在每次调用时都会生成一个新的空列表,那么这段代码就不正确了。在习惯于函数式语言的初学者也可能会被Python内置容器中的command-query separation设计决策所迷惑:那些没有特别返回内容的方法(即绝大多数变异方法)什么都不返回(具体地说,它们返回
^{pr2}$None
),它们正在“原地”完成所有工作。来自误解的错误很容易被发现,例如几乎可以肯定是一个bug,它将一个条目附加到名为
alist
的列表中,然后将namealist
重新绑定到None
(调用append
的返回值)。在虽然我提到的第一个问题是关于早期绑定,可能会误导那些认为绑定是延迟绑定的人,但是也有一些问题是相反的,即有些人的期望是早期绑定,而绑定则是延迟绑定。例如(使用假设的GUI框架…):
这将显示10个按钮,表示“Button#0”、“Button#1”等,但是,当单击时,每个按钮都将},因为{}中的
say
,它是{i
是晚绑定的(带有词法闭包)。一个修复方法是利用参数的默认值是早期绑定的这一事实(正如我在第一个问题中指出的那样!-)最后一行改成现在
lambda
的i
是一个带有默认值的参数,不再是一个自由变量(通过词法闭包查找),因此代码按预期工作(当然还有其他方法)。在相关问题 更多 >
编程相关推荐