码迷,mamicode.com
首页 > 编程语言 > 详细

Python语法(高级语法)- 命名空间和作用域

时间:2020-10-18 17:13:36      阅读:44      评论:0      收藏:0      [点我收藏+]

标签:col   filename   全局   直接   after   不可   rac   需要   lambda   

Python语法(高级语法)- 命名空间和作用域
 
命名空间(Namespace)
  • 命名空间是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的。
  • 命名空间提供了在项目中避免名字冲突的一种方法。各个命名空间是独立的,对象在同一个命名空间中不能有重名,但不同的命名空间可以重名。
 
技术图片
 

命名空间的类型
  • 内置名称(built-in names)
    • 比如函数名 abs、char 和异常名称 BaseException、Exception 等等。
    • 可以通过下面的方法查看内置名称:
>>> import builtins
>>> dir(builtins)
    • 全局名称(global names)
      • 模块中定义的名称,包括函数、类、其它导入的模块、模块级的变量和常量。
    • 局部名称(local names)
      • 类中定义的名称,包括数据属性,方法属性。
      • 函数中定义的名称,包括函数的参数、局部定义的变量。
 

命名空间的查找顺序
  • 局部的命名空间去 -> 全局命名空间 -> 内置命名空间
 
技术图片
 
命名空间的生命周期
  • 取决于对象的作用域,如果对象执行完成,则该命名空间的生命周期就结束。
 

 
对象的作用域
  • 作用域就是一个Python程序可以直接访问命名空间的正文区域。
  • 在一个python程序中,直接访问一个变量,会从内到外依次访问所有的作用域直到找到,否则会报未定义的错误。
  • Python中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。
  • 只有模块(module)、类以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的。
var_f0 = 789
while (var_f0 == 789):
    print("change var_f0......")
    var_f0 = 123123  # 在while中更新var_f0的值
 
print(var_f0)
 
输出:
change var_f0......
123123
 
 

作用域的类型
  • L(Local):最内层,包含局部变量。
    • 比如一个函数/方法内部。
  • E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。
    • 比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
技术图片
 
  • G(Global):当前脚本的最外层。
    • 比如当前模块的全局变量。
  • B(Built-in): 包含了内建的变量/关键字等。最后被搜索
 

作用域的查找顺序
  • L –> E –> G –> B
 
技术图片
 

 
全局变量和局部变量
  • 全局变量:定义在函数外的变量具有全局作用域。
    • 变量定义在模块的函数外,则在模块内具有全局作用域。
    • 变量定义在类内的函数外,则在类内具有全局作用域。
 
  • 局部变量:定义在函数内的变量具有函数内的局部作用域。
 
global 和 nonlocal关键字
  • 当内部作用域想修改外部作用域的变量时,需要用到global和nonlocal关键字。
 
用例1:在局部作用域中没有同名变量时,可以访问外部变量
# 全局变量,作用域:整个模块。
var_f0 = 123
 
def func1():
    # 局部变量,作用域:func1
    var_f1 = 456
 
    def func2():
        print("in func2 start......")
        print("var_f0:", var_f0)  # 在func2中可以访问外部变量
        print("var_f1:", var_f1)  # 在func2中可以访问外部变量
        print("in func2 end......")
 
    print("before func2: ")
    print("var_f0:", var_f0)
    print("var_f1:", var_f1)
    func2()
    print("after func2: ")
    print("var_f0:", var_f0)
    print("var_f1:", var_f1)
 
 
func1()
 
输出:
before func2:
var_f0: 123
var_f1: 456
in func2 start......
var_f0: 123
var_f1: 456
in func2 end......
after func2:
var_f0: 123
var_f1: 456
 
用例2:在局部作用域中不能直接修正外部变量
# 全局变量,作用域:整个模块。
var_f0 = 123
 
def func1():
    # 局部变量,作用域:func1
    var_f1 = 456
 
    def func2():
        print("in func2 start......")
        print("var_f0:", var_f0)  # 在func2中不可以访问
        print("var_f1:", var_f1)  # 在func2中不可以访问
 
 
        var_f0 = 789 # 这并不是在给模块变量var_f0赋值,而是在内部重新定义了同名变量,导致print("var_f0:", var_f0)出错。
        var_f1 = 789 # 这并不是在给模块变量var_f1赋值,而是在内部重新定义了同名变量,导致print("var_f1:", var_f1)出错。
        print("in func2 end......")
 
 
    print("before func2: ")
    print("var_f0:", var_f0)
    print("var_f1:", var_f1)
    func2()
    print("after func2: ")
    print("var_f0:", var_f0)
    print("var_f1:", var_f1)
 
 
func1()
 
输出:
before func2:
var_f0: 123
var_f1: 456
in func2 start......
var_f0: 123
Traceback (most recent call last):
  File "U:/Project/Python_Training/Pytho_Basic/zz_test.py", line 29, in <module>
    func1()
  File "U:/Project/Python_Training/Pytho_Basic/zz_test.py", line 24, in func1
    func2()
  File "U:/Project/Python_Training/Pytho_Basic/zz_test.py", line 15, in func2
    print("var_f1:", var_f1)  # 在func2中可以访问
UnboundLocalError: local variable ‘var_f1‘ referenced before assignment
 
用例3:在局部作用域中修正外部变量的方法用例1:在局部作用域中没有同名变量时,可以访问外部变量
# 全局变量,作用域:整个模块。
var_f0 = 123
 
def func1():
    # 局部变量,作用域:func1
    var_f1 = 456
 
    def func2():
        global var_f0   # 声明改变量为外部变量
        nonlocal var_f1 # 声明改变量为外部变量
 
        print("in func2 start......")
        print("var_f0:", var_f0)  # 在func2中可以访问
        print("var_f1:", var_f1)  # 在func2中可以访问
 
        var_f0 = 789 # 在func2中修正
        var_f1 = 789 # 在func2中修正
        print("in func2 end......")
 
    print("before func2: ")
    print("var_f0:", var_f0)
    print("var_f1:", var_f1)
    func2()
    print("after func2: ")
    print("var_f0:", var_f0)
    print("var_f1:", var_f1)
 
func1()
 
输出:
before func2:
var_f0: 123
var_f1: 456
in func2 start......
var_f0: 123
var_f1: 456
in func2 end......
after func2:
var_f0: 789
var_f1: 789
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Python语法(高级语法)- 命名空间和作用域

标签:col   filename   全局   直接   after   不可   rac   需要   lambda   

原文地址:https://www.cnblogs.com/JacquelineQA/p/13835667.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!