python变量作用域的一点思考

我们知道,python从某种程度上是支持函数式编程的,函数可以作为参数传递,也可以作为返回值返回,并且可以定义局部函数。
但是初学者面对这种函数式特性带来的变量作用域问题可能会有一点不适,
举个例子
def test():
        x=2
        def inner():
                t = x + 1
                x = t
                return t
       return inner

fun  = test()
fun()


我们可以看到执行fun()时会出错,因为在inner函数里,第一句 t = x + 1表面 x是一个外部变量,就是test函数里定义的x,
但是在第二句 x = t中对x进行了赋值,这是不允许的,也就是说内部函数可以引用外部函数中定义的变量,但是不能对其值
进行修改。为什么会有这个看起来比较奇怪的规则呢?我们从变量作用域的角度来分析:
在执行fun=test()之后,test里定义的x变量从理论上来说其生命周期已经结束了,但是fun函数(inner的值赋给了fun)里却引用了x,
肯定存在一种机制,使得inner函数把x的变量给“转过去”了。从语言实现的角度来看,可以在inner被return的时候做这种操作,因为
此时test内部的x的生命周期刚好结束,可以直接把x的值传到inner函数内部。这样一看inner内部对x的值进行修改貌似没啥问题啊,因为
变量已经传进去了。我们看下面的例子:
def test():
        x=2
        def inner():
              t = x +1
               x = t
              return t
       def inner2():
             t = x *2
             x = t
             return t
       return inner,inner2


test函数返回了两个内部函数。假设两个内部函数都对x的值进行了修改,会引起冲突问题。如果按照之前的方式在x变量生命周期结束时,
通过简单的变量值传递的方式进行,当其中一个函数修改x时,另一个函数里的x并不会改变,逻辑上就会有问题。因此需要以传地址的方式
进行,即传给inner和inner2的是变量x的地址,而且变量x在退出test函数的作用域时不能被回收,必须要从语言层面上找一个公共的地方存x。
这样实现起来就比较复杂了,至少没有一个简单的trick的方式。但是如果x是不可变的呢?那就简单了,把x的值传给inner和inner2就可以了,之后
不需要管,因为x不可变,不存在冲突问题和逻辑问题,实现起来非常的顺畅。
所以依我看来,python之所以会有这样奇怪的规则,很可能是最初实现python时不想带来太多的复杂度。我们可以看到python3提供了 nonlocal
关键字来实现对外层变量的修改,由此可见一斑。

你可能感兴趣的:(python变量作用域的一点思考)