1.7 - 命名空间与作用域

1.7.1 命名空间

  命名空间(NameSpace)是一个从名称到对象的映射。大部分命名空间由 字典 实现,内置命名空间由 builtins 模块实现。命名空间之间是独立的,避免了命名冲突。

 

1.7.2 命名空间的分类

  1)内置命名空间

    包含所有Python内置对象的名称,在 解释器启动时 创建,持续到解释器终止。被所有的Python文件所共享。

  2)全局命名空间

    一个.py 文件即是一个python模块,每个模块都有一个各自的全局命名空间。记录了模块的 全局变量、类、函数、导入的其它模块 等。在 模块被读入时 创建,持续到解释器退出。

  3)局部命名空间

    记录了函数的 变量的参数 。在 函数被调用时 创建,持续到函数调用结束。

  命名空间的查找顺序默认优先级局部命名空间 > 全局命名空间 > 内置命名空间 

 

1.7.3 exel()函数和eval()函数【都可以执行字符串形式的 python 代码】

  eval(expression [,  globals [, locals ]]);只能接收一个表达式;返回表达式的结果;

  exec(object [, globals [,locals ]]);可以接收多个表达式组成的代码块;无返回值,返回None;

  注:globals 和 locals 参数为字典,指代 表达式的全局命名空间和局部命名空间,并且如果函数包含了globals和locals参数,表达式执行的时候只能从参数globals 和 locals 的命名空间中取值

    如果locals参数没有传递而只传递了globals参数,那么 locals 取和globals相同的值。

# 验证eval函数

a = 1
b = 2

def fun1():
  a = 3
  
  print(eval("a+b"))  # 5
  print(eval("a+b", {'a':4, 'b':5})) # 9
  print(eval("a+b", {'a':4, 'b':5}, {'a':6, 'x':7})) # 11
  print(eval("a+b", {'a':6, 'x':7}, {'a':8, 'y':9})) # 命名空间找不到变量b,报错。

 

1.7.4 作用域

  python程序可以直接访问的命名空间的正文区域。

  作用域分类:局部作用域(Local) > 闭包函数外的函数中(Enclosing) > 全局作用域(Global) > 内置作用域(Built-in) ;当前作用域内找不到变量值的时候会自动向下一个作用域寻值。

  只有模块(module)、类(class)以及函数(def、lambda)才会引入新的作用域。案例如下:

# if 、while等分支不会引入新的作用域

a = 123

if  a == 123:
  a = 456
  print(a) # 456

print(a) # 456

 

1.7.5 人为指定变量的作用域

1 # 下面代码会报错,分析:表达式 a+1 在执行的时候会发生:变量a在执行之前引用。
2 
3 def  fun2():
4   a = a + 1
5   print(a)
6 
7 a = 123
8 fun2() # 
9 print(a) 

分析: 8th 调用fun2函数,会报错:在fun2函数中,将表达式 a+1 赋值给 a,语法检查器检查到 局部命名空间中有定义变量a,所以 在执行表达式的时候,不会去访问全局变量a,而在局部作用域中,变    量a的赋值又是在表达式执行之后,所以会报 “变量a在赋值之前引用” 错误。

解决

# 解决 
def  fun2():
  global  a    # 通过global关键字指定局部作用内的a全部使用 全局变量
  a = a + 1
  print(a)

a = 123
fun2() 
print(a) 

 

global关键字和 nonlocal关键字:

如上示例:global强制使用全部变量;nonlocal强制使用闭包函数外函数内变量!!!

 

结尾小甜点:

def outer():
  lst = [1,2]

  def inner():
    res = lst.append(3)
    lst = lst.append(3)
    print(lst,  res)     #  None,  None

outer()

为啥会输出两个None?因为append函数没有返回值!

 

posted @ 2024-01-14 19:45  橘子葡萄火龙果  阅读(10)  评论(0)    收藏  举报