Labfans是一个针对大学生、工程师和科研工作者的技术社区。 | 论坛首页 | 联系我们(Contact Us) |
![]() |
![]() |
#1 |
高级会员
注册日期: 2019-11-21
帖子: 3,006
声望力: 66 ![]() |
![]()
我正在考虑从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], [], [], []] 提前致谢 回答: 对相同(可变)对象的引用与对独立对象的引用的混淆确实是一个“陷阱”(受所有非功能性语言的折磨,这些语言具有可变的对象,当然还有引用)。初学者的Python代码中常见的错误是滥用可变的默认值,例如: def addone(item, alist=[]): alist.append(item) return alist 如果目的是让addone保持自己的状态(并将一个不断增长的列表返回给后续的调用者),则此代码可能是正确的,就像static数据在C语言中一样;如果编码器错误地假设每次调用都会创建一个新的空列表,这是不正确的。 习惯使用函数式语言的初学者也可能会因Python内置容器中的命令查询分离设计决策而感到困惑:不需要特别返回的变异方法(即,绝大多数变异方法)什么都不返回(具体来说,他们返回None )-他们正在“就地”完成所有工作。误解引起的错误很容易发现,例如 alist = alist.append(item) 几乎可以肯定是个错误-它会将项目追加到名称alist引用的列表中,然后将名称alist重新绑定为None ( append调用的返回值)。 虽然我提到的第一个问题是关于早期绑定的,但可能会误导认为绑定是较晚的人们,但有些问题则相反,有些人期望在绑定早期时就进行早期绑定。 ,反而晚了。例如(使用假设的GUI框架...): for i in range(10): Button(text="Button #%s" % i, click=lambda: say("I'm #%s!" % i)) 这将显示十个按钮,分别显示“ Button#0”,“ Button#1”等,但是当单击时,每个按钮都会say是#9 ,因为lambda的i是后期绑定的(带有a词法闭包)。解决方法是利用参数的默认值是早绑定的事实(正如我所指出的第一个问题!-),并将最后一行更改为 click=lambda i=i: say("I'm #%s!" % i)) 现在, lambda的i是具有默认值的参数,不再是自由变量(通过词法闭包查找),因此代码按预期工作(当然,还有其他方法)。 更多&回答... |
![]() |
![]() |