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程序“去哪里”找到变量。

原文地址:https://www.cnblogs.com/sunchao1984/p/5377680.html