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

时间:2018-07-31 01:36:37

标签: python scope sml

According to my programming language class,使用的语言使用词法作用域

  

在以下环境中评估函数主体:   函数是定义的,而不是函数调用的环境。

例如,SML遵循以下行为:

val x = 1
fun myfun () =
    x
val x = 10
val res = myfun()  (* res is 1 since x = 1 when myfun is defined *)

另一方面,Python不遵循以下行为:

x = 1
def myfun():
    return x
x = 10
myfun()  # 10 since x = 10 when myfun is called

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

4 个答案:

答案 0 :(得分:4)

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

get_sheet_by_name()

第一行声明一个变量val x = ref 1 fun myfun () = !x val () = x := 10 val res = myfun () ,该变量引用一个整数并将引用的单元格设置为1。函数主体取消引用x以返回引用的单元格中的值。第三行将引用的单元格设置为10。第四行中的函数调用现在返回10。

我使用笨拙的x语法来修复顺序。声明的添加仅是因为其对val () = _的副作用。也可以这样写:

x

环境是不可变的-特别是val x = ref 1 fun myfun () = !x; x := 10; val res = myfun () 始终指向相同的存储单元-但是某些数据结构(参考单元和数组)是可变的。

答案 1 :(得分:3)

您的Python myfun正在使用其定义环境中的x变量,但是该x变量现在拥有一个新值。词法作用域意味着函数从定义位置记住变量,但这并不意味着它们必须在定义函数时对这些变量的值进行快照。

您的标准ML代码具有两个 x变量。 myfun正在使用第一个变量。

答案 2 :(得分:3)

在Python中,就像在SML或(现代)Lisp中一样,在定义函数的环境中评估函数的主体。因此,所有三种语言都在词法范围内。

在Python和Lisp中,环境是可变的。也就是说,您可以为现有变量分配一个新值,从而使该变量所属的环境发生变化。在该环境中定义的所有函数都将在该环境中进行评估-这意味着它们将看到变量的新值。

在SML中,环境不是可变的;环境不能更改,没有没有新值,因此毫无疑问函数是否会看到该新值。

语法可能会引起误解。在ML中,val x = 1val x = 10都定义了一个全新的变量。在Python中,x = 1x = 10是赋值语句-它们会重新赋值给现有变量,仅当尚无该变量时才定义一个新变量。 (您在Lisp中看不到这一点,例如letsetq很难混淆。)


顺便说一句,具有可变变量的闭包在功能上等同于可变对象(从面向对象的角度来看),因此Lisp(和Python)的这一功能传统上非常重要。


作为一个旁注,Python实际上对全局名称空间(及其上方的内置函数)有一些特殊的规则,因此您可以辩称示例中的代码在技术上不依赖于词法作用域。但是,如果将整个内容放在一个函数中并调用该函数,那么它肯定是词法作用域的一个示例,因此全局问题在这里实际上并不那么重要。

答案 3 :(得分:1)

TL;DR(如下)给出了Python的词法作用域的简单示例 ...

但是首先让我添加一些 rationale 来帮助 me 理解问题(并写下此答案)。

在Python的变量评估中有两个相互重叠的概念,这可能会造成一些混乱:

  • 一个是Python用来评估变量的递归(内存范围)查找,即著名的BGEL顺序(内置<全局<封闭<本地范围)。
  • 另一个是定义和/或评估函数的范围

正如OP所说,当我们可以切换变量的值(“ x”)或可以定义一个函数(使用“ {{1} }“)甚至没有事先声明其中的变量(” x“);例如,

x

这可能会使有关变量和内存中实际对象的名称绑定的知识更加混乱,从而使变量的 value 概念有些松散(与C等其他语言相比)。

> def f(): print(x) > x = 1 > f() 1

Python 词法作用域在起作用

TL;DR

然后我们可以看到,在评估变量时,递归(BGEL)范围搜索策略正在遵守定义了功能'> def f(): print(x) > def g(foo): x = 99 foo() print(x) > x = 1 > g(f) 1 99 '的作用域局部和之上