命名空间
1)3种命名空间
内置命名空间( 由builtins模块实现),在解释器启动的时候会准备好这个命名空间,然后持续到解释器停止,所以不用import就可以直接适用其中的内置函数/类名称等。它是为所有的.py文件服务的。
在模块被读入时会创建一个全局命名空间,它是为当前.py文件服务的。全局命名空间也是持续到解释器退出。
#通过以下命令可以返回全局的命名空间(返回的是一个字典,由此可见全局命名空间记录的东西是字
#典实现的)。
print(globals())
局部命名空间包含函数中定义的名称,记录了函数的变量、参数等 一个函数的局部命名空间在这个函数被调用时创建,持续到函数结束。
#通过在定义的函数中执行如下命令会返回当前局部命名空间(也是由字典来记录),需要注意的是若将
#该命令放到全局区域的话输出结果与print(globals())相同。
print(locals())
命名空间的查找顺序为:局部命名空间 -> 全局命名空间 -> 内置命名空间。所以在局部命名空间print一个未定义的变量,就会区全局命名空间找......
2)eval(expression[, globals[, locals]]) 和exec(object[, globals[, locals]])
都可以将字符串当成python程序来执行,它们的区别是eval函数只能执行单个表达式,并返回执行的结果;而exec(函数还可以执行代码块,无返回值(return None)。
string = "4345789"
lst = [int(i) for i in string]
print(sum(lst)) # 40
print(eval('+'.join(string))) # 40
exec('print('+'+'.join(string)+')') # 40
需要注意的是eval和exec后面二个可选参数用来指定全局命名空间和局部命名空间(字典的形式)。如果不指定locals,则globals和locals是相同的,如下所示二条语句相同:
3)dir函数
用来收集模块中定义的名称,
import builtins
# 可以用来收集内置命名空间中builtin中定义的名称。不带参数时,返回当前.py文件中定义好的一些名称。
print(dir(builtins))
作用域
1)四种作用域
#在当前作用域如果找不到对应名称,则去更大一级作用域去找,直到最后找不到就会报错.作用域依次
#增大的顺序为局部作用域(Local)、闭包函数外的函数中(Enclosing)、全局作用域(Global)、
#內建作用域(Built-in)。
# 如下示例是一个闭包函数:闭包函数需要满足三要素:
#1)需要是嵌套函数
#2)外部函数的返回值是内部函数的引用
#3)内部函数中使用到了外部函数的变量或参数
#一般来说,如果一个函数结束,函数内部的变量、参数会被释放掉;而闭包则不同,它在外部函数结束
#时,会把内部函数中用到的外部函数的变量、参数保存到内部函数的__closure__属性中,以提供给内部
#函数使用。
def outer():
a = c + 2 # Enclosing可以调用全局变量c
def inner():
b = c + 3 # 局部作用域可以调用全局变量c
print(a + b) # 局部作用域可以调用Enclosing变量a
inner()
c = 1 # 全局变量
print(c) # 调用全局变量c
# abs是内置函数、int是内置类,它们都在内建作用域builtins模块中
num1 = abs(-100)
num2 = int(3.141592653)
2)global 和 nonlocal
#当内部作用域想要给外部作用域的变量重新赋值时,可以用 global 或 nonlocal 关键字
def outer():
global a, b # 声明当前作用域的a,b为全局变量
a, b, c, d = 3, 4, 5, 6
print(a, b)
def inner():
global a, b # 声明当前作用域的a,b为全局变量
nonlocal c, d # 声明当前作用域的c,d为Enclosing变量
a, b, c, d = 7, 8, 9, 0
inner()
print(c, d)
a, b = 1, 2
outer()
print(a, b)