• python初学者笔记——命名空间


    对于初学者而言,闭包的概念一直都是很难理解的。

    我在学习的时候,网上查了那么多资料,依然是一知半解。

    直到后来我看了这篇文章:http://simeonfranklin.com/blog/2012/jul/1/python-decorators-in-12-steps/

    这是一篇很好的文章,由浅入深的告诉你到底闭包,装饰器都是什么东西。

    E文不过关?没关系,我来用我自己的理解和你们聊聊命名空间、闭包和装饰器的那些事儿。

    前提:

    阅读这篇文章的前提,是你要对Python,有基础的理解,如果你有兴趣,但是对python还没有理解,我推荐你去读下面的教程:

    www.liaoxuefeng.com

    同时,微信公众号:easypython,中文名:说人话的python分享,也是很不错的教程,建议有一定入门基础的同学尝试。

    说人话的python实战计划:http://study.163.com/course/introduction/1002794001.htm

    开始:

    命名空间

    命名空间(namespace)这个概念,有时也被称为“作用域”,在大多数讲解闭包的时候都会有所涉及。

    那什么是命名空间/作用域呢?

    这两个概念,是用来描述一个变量的属性的,它们的意思,就是字面意思:“这个变量起名字的地方/这个变量起作用的域”.

    我们用实例来说明一下:

    def func():
        x = 1

     简单的函数,这个函数定义了一个叫做x的变量,且给了它一个值:1

    那么,如果我们print这个变量呢?(我用注释来表示输出)

    def func():
        x = 1
        print(x)
    
    func()
    
    # 1

    好像完全是废话嘛!print(x)不显示1,难道还显示别的?

    那好,我们换一种情况,如果我们在函数体外面print(x)呢?

    def func():
        x = 1
    
    print(x)
    
    # Traceback 后面一大堆我省略了...
    # NameError: name 'x' is not defined

    报了一个错误,错误的类型是name error,名称错误,错误的细节是:x没有定义。

    看到这里,细心的朋友应该就知道我说这么多废话是什么意思啦!

    x定义在函数体内部嘛,它的“作用范围”就仅仅是函数体内才能用!

    你想把X打印出来?想把x加1?想把x乘以2?对不起,请到函数体内部去执行,外面,python不认识它。

    说到python不认识它,其实是指“python的解释器”不认识它,解释器具体不多解释,你可以简单的理解为你电脑的python程序。

    好吧好吧,python不认识它,那么如果,我换一种情况呢?我把两个语句交换一下位置?

    x = 1
    
    def func():
        print(x)
    
    func()
    
    # 1

    咦?你这个骗子,你不是说python不认识它吗?现在x不在函数体内定义了(事实上函数体内什么定义都没有~)

    你怎么又认识它了?

    问到这个问题,就得说一说python程序,读取一个变量的方法了。

    简单的说,四个字:由内而外

    python先去查函数体内部:

    1.我找到了,打印!

    2.我找不到,我去找外面,找到了,打印!

    3.我找不到,我去找外面,我还是找不到! NameError: 我找不到变量,你丫没定义吧?

    看,就是这么个顺序。

    那么找不到的x变量去哪里了?

    比如这个程序:

    def func():
        x = 1
    
    print(x)

    x呢?x去哪里了?

    答案是x被python解释器给“回收”了,所谓回收,你可以简单的理解成删除了、杀死了。

    这里要引入一个概念,就是变量的“存活时间”

    我写一下你就了解了(为了方便的标记函数体的结束,我写了一个返回字符串‘done’的return语句):

    def func():
        
        x = 1  
        # x的存活时间开始,在x=1这行下面操作x才可以!
        
        return 'Done'  # 函数体结束,x被python杀死了。

    就是如上代码中所表述的意思:

    一个函数体内变量的存活时间,从定义它的那一刻开始,直到函数体结束为止。

    我们可以通过一个很方便的、python给定我们的方法,来判断函数体内部还“活着”的变量有哪些,这个方法是locals()

    我们看一个代码:

    def func():
    
        a = '哎呀'
        b = '我们'
        c = '还活着'
        print(locals())
    
    
    func()
    
    # {'a': '哎呀', 'c': '还活着', 'b': '我们'}

    看,locals()其实是一个字典,他列出了所有的“变量:变量值”这样的“键-值对”,而且字典是无序的。

    locals()里面存的全部都是当前“活着”的变量,我们看另外一个例子:

    def func():
    
        a = '哎呀'
        b = '我们'
        c = '还活着'
        print(locals())
        d = '我还没出生'
    
    
    func()
    
    # {'b': '我们', 'c': '还活着', 'a': '哎呀'}


    看,locals()里面就没有变量d什么事情了,因为d在那个时候“还没出生”呢。

    那么外部的变量呢?

    x = 1
    def func():
    
        a = '内部'
        print(locals())
        print(x)
    
    
    func()
    
    # {'a': '内部'}
    # 1


    看到了吧,内部变量只有一个,locals也打印出来了,但是x还是正常的可以打印。

    因为python在内部找不到,于是就去外面找了,外部的变量,可以用globals()检查到,但是这个很长…………

    x = 1
    def func():
    
        a = '内部'
        print(locals())
        print(globals())
    
    
    func()
    
    # {'a': '内部'}
    # ....(一大堆我就不粘贴了)..... 'x': 1}

    命名空间/作用域的概念就是这样,它决定了python程序“去哪里”找到变量。

  • 相关阅读:
    Java中的变量
    Java是什么
    leetcode 75. 颜色分类
    leetcode 283. 移动零
    剑指 Offer 65. 不用加减乘除做加法
    剑指 Offer 53
    剑指 Offer 58
    剑指 Offer 58
    剑指 Offer 57
    剑指 Offer 57. 和为s的两个数字
  • 原文地址:https://www.cnblogs.com/sunchao1984/p/5377680.html
Copyright © 2020-2023  润新知