前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >技巧(一)、Scope and Namespace

技巧(一)、Scope and Namespace

作者头像
狼啸风云
发布2023-10-07 15:07:51
1900
发布2023-10-07 15:07:51
举报
文章被收录于专栏:计算机视觉理论及其实现

1,基础概念

1.1 命名空间(namespace)  

命名空间是名字和对象的映射。也就是可以把一个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)  

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

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

  1. 最里面的局部作用域
  2. 外层函数的局部作用域
  3. 模块的全局作用域
  4. 包含python内置对象的最外层作用域
1.3 赋值(assignment)  

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

2,global和nonlocal语句

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

代码语言:javascript
复制
global var1, var2

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

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

 一个nonlocal和global的测试例子

代码语言:javascript
复制
def test():
    def do_local():
        spam = "local spam"
    def do_nonlocal():
        nonlocal spam    
        spam = "nonlocal spam"
    def do_global():
        global spam
        spam = "global spam"
    spam = "test spam"
    do_local()
    print("after local assignment:", spam)   #输出:test spam
    do_nonlocal()
    print("after nonlocal asssignment:", spam)   #输出:nonlocal spam
    do_global()
    print("after global assignment:", spam)    #输出:nonlocal spam

test()
print("in global scope:", spam)  #输出:global spam

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

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

跟进一步测试nonlocal

代码语言:javascript
复制
def test():
    def do_nonlocal():
        nonlocal spam
        def do_nonlocal2():
            nonlocal spam
            spam = "nonlocal2 spam"  #修改了test()中spam的绑定
        do_nonlocal2()
    spam = "test spam"
    do_nonlocal()
    print("after nonlocal2 asssignment:", spam)  #输出:nonlocal2 spam
test()

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1,基础概念
    • 1.1 命名空间(namespace)  
      • 1.2 作用域(scope)  
        • 1.3 赋值(assignment)  
        • 2,global和nonlocal语句
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档