Python范围界定规则是否符合词法范围界定的定义?

2024-04-25 21:09:37 发布

您现在位置:Python中文网/ 问答频道 /正文

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}$

那么为什么is Python described as using lexical scoping?在


Tags: thetoenvironmentismyfunctionresval
3条回答

在Python中,就像在SML或(现代)Lisp中一样,函数体是在定义它的环境中计算的。所以,这三种语言都有词汇范围。在

在Python和Lisp中,环境是可变的。也就是说,你可以给一个现有的变量分配一个新的值,这会改变这个变量所处的环境。在该环境中定义的任何函数都将在该环境中求值,这意味着它们将看到变量的新值。在

在SML中,环境是不可变的;环境不能改变,那里没有新值,因此函数是否会看到新值没有问题。在

语法可能有点误导。在ML中,val x = 1和{}都定义了一个全新的变量。在Python中,x = 1和{}是它们重新分配给现有变量的赋值语句,只有在还没有该名称的情况下才定义一个新变量。(在Lisp中看不到这一点,例如,let和{}很难混淆。)


顺便说一句,具有可变变量的闭包在功能上等同于可变对象(在OO的意义上),因此Lisp(和Python)的这一特性在传统上非常重要。在


顺便说一句,Python实际上对全局名称空间(以及上面的内置名称空间)有一些特殊的规则,因此您可以争辩说,您的示例中的代码在技术上不依赖于词法作用域。但是如果你把所有的东西放在一个函数里面,然后调用这个函数,那么它肯定是词法范围界定的一个例子,所以全局问题在这里并不那么重要。在

您的Pythonmyfun正在使用定义它的环境中的x变量,但是这个x变量现在保存了一个新值。词法作用域是指函数从定义变量的地方记住变量,但这并不意味着它们必须在定义函数时对这些变量的值进行快照。在

{em2>你的标准代码有两个。myfun正在使用第一个变量。在

除了@abarnert和@user2357112的响应外,它还可以帮助您考虑Python代码的SML等价物:

val x = ref 1
fun myfun () = !x
val () = x := 10
val res = myfun ()

第一行声明一个变量x,它引用一个整数并将引用的单元格设置为1。函数体取消引用x以返回被引用单元格中的值。第三行将引用单元格设置为10。第四行中的函数调用现在返回10。在

我使用了笨拙的val () = _语法来修正排序。添加声明仅仅是为了它对x的副作用。也可以写下:

^{pr2}$

环境是不可变的,特别是x总是指向同一个内存单元,但是某些数据结构(引用单元和数组)是可变的。在

相关问题 更多 >