zoukankan      html  css  js  c++  java
  • Python基础-作用域和命名空间(Scope and Namespace)

    在Python中,对象是独立的,不同作用域中的不同名字都可以被绑定在同一个对象上,当然对这个对象的修改会影响所有的引用。赋值操作就是名字和对象的绑定或重绑定。这和C++中的引用是一样的。

    1,基础概念

    1.1 命名空间(namespace)  

    namespace is a mapping from names to objects

    命名空间是名字和对象的映射。也就是可以把一个namespace理解为一个字典,实际上很多当前的Python实现namespace就是用的字典。各个命名空间是独立的,没有任何关系的,所以一个命名空间中不能有重名,但不同的命名空间是可以重名而没有任何影响。

    那么哪些可以是一个namespace呢,比如Python的built-in names(包括内置函数,内置常量,内置类型);一个模块的global names(这个模块定义的函数,类,变量);一个函数的所有local names;还有一个类对象的所有属性(数据成员,成员函数)都组成一个命名空间。

    命名空间都是有创建时间和生存期的。对于Python built-in names组成的命名空间,它在Python解释器启动的时候被创建,在解释器退出的时候才被删除;对于一个Python模块的global namespace,它在这个module被import的时候创建,在解释器退出的时候退出;对于一个函数的local namespace,它在函数每次被调用的时候创建,函数返回的时候被删除。

    [总结]一个模块的引入,函数的调用,类的定义都会引入命名空间,函数中的再定义函数,类中的成员函数定义会在局部namespace中再次引入局部namespace。

    1.2 作用域(scope)  

    scope is a textual region of a Python program where a namespace is directly accessible.

    作用域是Python程序(文本)的某一段或某些段,在这些地方,某个命名空间中的名字可以被直接引用。这个作用域就是这个命名空间的作用域。

    一个Python程序的几个作用域:

    1. 最里面的局部作用域
    2. 外层函数的局部作用域
    3. 模块的全局作用域
    4. 包含Python内置对象的最外层作用域

    关于作用域,参加Python基础-函数这片博客中2小节的例子。

    1.3 赋值(assignment)  

    Assignments do not copy data — they just bind names to objects.

    赋值操作不会拷贝,只是把名字和对象做一个绑定。也就是赋值语句是起一个绑定或重绑定的作用(bind or rebind)。函数调用的参数传递是赋值,不是拷贝。

    2,global和nonlocal语句

    global语句用来声明一系列变量,这些变量会引用到当前模块的全局命名空间的变量(module-level namespace),如果该变量没有定义,也会在全局空间中添加这个变量。

    global var1, var2

     nonlocal语句(nonlocal是Python3.2引入的)

    Python2.7中还没有nonlocal语句。nonlocal语句用来声明一系列的变量,这个声明会从声明处从里到外的namespace去搜寻这个变量(the nearest enclosing scope),直到模块的全局域(不包括全局域),找到了则引用这个命名空间的这个名字和对象,若作赋值操作,则直接改变外层域中的这个名字的绑定。nonlocal语句声明的变量不会在当前scope的namespace字典中加入一个key-value对,如果在外层域中没有找到,则如下报错。

    >>>SyntaxError: no binding for nonlocal 'spam' found

     一个nonlocal和global的测试例子

     1 def test():
     2     def do_local():
     3         spam = "local spam"
     4     def do_nonlocal():
     5         nonlocal spam    
    6
    spam = "nonlocal spam" 7 def do_global(): 8 global spam 9 spam = "global spam" 10 spam = "test spam" 11 do_local() 12 print("after local assignment:", spam) #输出:test spam 13 do_nonlocal() 14 print("after nonlocal asssignment:", spam) #输出:nonlocal spam 15 do_global() 16 print("after global assignment:", spam) #输出:nonlocal spam 17 18 test() 19 print("in global scope:", spam) #输出:global spam

    第5行的语句:nonlocal spam 没有在函数do_nonlocal()的域中创建一个变量,而是去引用到了外层的,10行定义的spam。

    第8行的global spam,在全局域中创建了一个name,9行将其绑定在字符串常量对象"global spam"上。

    跟进一步测试nonlocal

     1 def test():
     2     def do_nonlocal():
     3         nonlocal spam
     4         def do_nonlocal2():
     5             nonlocal spam
     6             spam = "nonlocal2 spam"  #修改了test()中spam的绑定
     7         do_nonlocal2()
     8     spam = "test spam"
     9     do_nonlocal()
    10     print("after nonlocal2 asssignment:", spam)  #输出:nonlocal2 spam
    11 test()

    do_nonlocal2()中的spam引用的是其外面的二层,也就是test()函数域中的spam。

    参考:

    http://docs.python.org/3.3/tutorial/classes.html#python-scopes-and-namespaces   Python文档

    http://docs.python.org/3.2/reference/simple_stmts.html  Python文档-simple statement

  • 相关阅读:
    POJ 3630 Phone List/POJ 1056 【字典树】
    HDU 1074 Doing Homework【状态压缩DP】
    POJ 1077 Eight【八数码问题】
    状态压缩 POJ 1185 炮兵阵地【状态压缩DP】
    POJ 1806 Manhattan 2025
    POJ 3667 Hotel【经典的线段树】
    状态压缩 POJ 3254 Corn Fields【dp 状态压缩】
    ZOJ 3468 Dice War【PD求概率】
    POJ 2479 Maximum sum【求两个不重叠的连续子串的最大和】
    POJ 3735 Training little cats【矩阵的快速求幂】
  • 原文地址:https://www.cnblogs.com/livingintruth/p/3296010.html
Copyright © 2011-2022 走看看