5

Scope-1-py

命名空间

参考来源:官方 tutorial,python2.7.11

在python中的命名空间是一种从名字到对象的映射,大多数的命名空间都是被当做字典实现的,命名空间的例子有:

built-in的名字,包括exception的名称;在一个模块中的全局名称;一个新创建的函数的本地名称;某种意义上

对象属性的设置也能成为一个命名空间。不同命名空间之间是没有关系的。

命名空间的创建和生存周期是不同的,包含内建名称的命名空间在python解释器开始的时候被创建;一个已定义的模块的全局命名空间,在被读取进来的时候被创建,通常情况下,这个模块将会持续到解释器停止;当被读取进来的文件或者全局定义的名称都会被包含在一个叫做__main__的模块,当然内建的名称将会被包含在__builtin__的模块下。

作用域

一个作用域是指一个python程序的文法区域textual region,并且一个命名空间将会直接接触它。直接接触的意思是,当引用一个不明确的名称时,程序将会在命名空间中寻找。

作用域虽然是静态决定的,但是却是动态使用的,执行的时候最少会被三层作用域直接接触:

  • 最内层作用域,将会被首先搜索,包括本地作用域。
  • 封闭区的作用域,比如被嵌套在其它函数的函数。
  • 包含当前模块的全局名称。
  • 最外层的作用域是built-in的名称。

以上就是所谓的LEGB规则

所有的在内部作用域外面的变量,仅仅是可读的,如果直接在内部修改它们,那么只是会copy一份变量到本地作用域,并不会改变全局变量。

通常本地作用域引用当前函数的本地名称,当在函数外的时候,这个时候的本地作用域引用的作用域是全局作用域---这个模块的命名空间。

classinstance的作用域

python的类对象有两种运算操作:属性引用和实例化,类的所有有效的属性名即是类命名空间内的所有名称。每个抽象类在被创建以后会有五个属性值:['__dict__', '__name__', '__bases__', '__doc__', '__module__']。其中的__dict__即是描述类的命名空间的。

同样python的类实例也是有初始化的属性值的:也有它自己的属性,只不过不同的是仅有['__dict__', '__class__']。需要了解的是类属性和类实例的属性还是有不同的,类的属性会是共有的,而类实例的属性是私有的。类和类实例都有各自的命名空间,不同的是在类实例中它还会指向类的namespace,如果在调用实例的属性值如果找不到的话,它还是会去找它所属的类实例的namespace

可以用locals()globals()来分别查看局部命名空间和全局命名空间。

python中的lambda

其实python中的lambda 并不是真正的lambda知乎-python-lambda,这个链接中的例子我一开始我也很困惑。

def counter():
    count = 1
    def inner():
        count += 1
        return count
    return inner

>>>counter()()
>>> UnboundLocalError: local variable 'count' referenced before assignment

再看另外一个与上面这个很相似的例子:

def counter():
    count = 1
    def inner():
        print count
        return count
    print inner()
    return inner

counter()()

从上面这两个例子中可以看出来,当修改变量的时候,如果没有声明nonlocal或者global,那么,python会将这个变量编程local,

从这点上来说,python中的closure并算不上是真正的闭包,对闭包没有完整的进行实现。所以后来在python3中的nonlocal关键字

的出现算得上是对闭包的修补吧。

相比之下,js的闭包反而算得上是真正得闭包。

Scope-Php