According to my programming language class,在使用词汇范围的语言中
The body of a function is evaluated in the environment where the function is defined, not the environment where the function is called.
例如,SML遵循以下行为:
val x = 1
fun myfun () =
x
val x = 10
val res = myfun() (* res is 1 since x = 1 when myfun is defined *)
另一方面,Python不遵循以下行为:
^{pr2}$
在Python中,就像在SML或(现代)Lisp中一样,函数体是在定义它的环境中计算的。所以,这三种语言都有词汇范围。在
在Python和Lisp中,环境是可变的。也就是说,你可以给一个现有的变量分配一个新的值,这会改变这个变量所处的环境。在该环境中定义的任何函数都将在该环境中求值,这意味着它们将看到变量的新值。在
在SML中,环境是不可变的;环境不能改变,那里是没有新值,因此函数是否会看到新值没有问题。在
语法可能有点误导。在ML中,}都定义了一个全新的变量。在Python中,}是它们重新分配给现有变量的赋值语句,只有在还没有该名称的情况下才定义一个新变量。(在Lisp中看不到这一点,例如,}很难混淆。)
val x = 1
和{x = 1
和{let
和{顺便说一句,具有可变变量的闭包在功能上等同于可变对象(在OO的意义上),因此Lisp(和Python)的这一特性在传统上非常重要。在
顺便说一句,Python实际上对全局名称空间(以及上面的内置名称空间)有一些特殊的规则,因此您可以争辩说,您的示例中的代码在技术上不依赖于词法作用域。但是如果你把所有的东西放在一个函数里面,然后调用这个函数,那么它肯定是词法范围界定的一个例子,所以全局问题在这里并不那么重要。在
您的Python
myfun
正在使用定义它的环境中的x
变量,但是这个x
变量现在保存了一个新值。词法作用域是指函数从定义变量的地方记住变量,但这并不意味着它们必须在定义函数时对这些变量的值进行快照。在{em2>你的标准代码有两个。
myfun
正在使用第一个变量。在除了@abarnert和@user2357112的响应外,它还可以帮助您考虑Python代码的SML等价物:
第一行声明一个变量
x
,它引用一个整数并将引用的单元格设置为1。函数体取消引用x
以返回被引用单元格中的值。第三行将引用单元格设置为10。第四行中的函数调用现在返回10。在我使用了笨拙的
^{pr2}$val () = _
语法来修正排序。添加声明仅仅是为了它对x
的副作用。也可以写下:环境是不可变的,特别是
x
总是指向同一个内存单元,但是某些数据结构(引用单元和数组)是可变的。在相关问题 更多 >
编程相关推荐