您的当前位置:首页正文

Python基础(十四): 函数作用域

来源:要发发知识网

一、基本概念

1、变量的作用域
  • 变量的作用范围: 可操作范围

  • Python是静态作用域, 也就是说在Python中, 变量的作用域源于它在代码中的位置, 在不同的位置, 可能有不同的命名空间

2、命名空间
  • 命名空间是作用域的体现形式

  • 表示变量不同的具体的操作范围

3、Python-LEGB
  • L-Local: 函数内的命名空间
    • 作用范围: 当前整个函数体
    def test():
        a = 10
        print(a)
    test()      # 打印: 10
    
    • a的作用范围只在test函数中
  • E-Enclosing function locals: 外部嵌套函数的命名空间
    • 作用范围: 闭包函数
    def test():
        a = 10
        def inner():
            print(a)
        inner()
    test()      # 打印: 10
    
    • a的作用域, 在整个闭包函数test
  • G-Global: 全局命名空间
    • 作用范围: 当前模块(文件)
    a = 10
    def test():
        print(a)
    test()  # 打印: 10
    
    • a的作用域, 在整个模块当中, 可以理解为当前文件
  • B-Builtin: 内建模块命名空间
    • 作用范围: 所有模块(文件)
    print("aaa")
    
    • print函数, 在所有文件中都可以使用
  • 注意:
    • Python中没哟快级作用域
    • 快级作用域: 代码块中, 比如 if while for 后的代码块
  • LEGB规则: 会按照 L -> E -> G -> B 的顺序进行查找

二、基础命名空间的常见变量类型

1、局部变量

  • 在一个函数内部定义的变量

  • 作用域为函数内部

  • 查看局部变量, 可以使用函数locals()

2、全局变量

  • 在函数外部, 文件最外层定义的变量

  • 作用域为整个文件内部

  • 查看全部变量, 可以使用函数globals()

3、注意点

  • 访问原则:

    • 从内到外
  • 结构规范:

    • 全局变量
    • 函数定义: 使用和修改
    • 后续代码
  • 全局变量和局部变量重名

    • 获取: 就近原则
    • 修改: global 全部变量
  • 命名规范:

    • 全局变量: g_xxx

三、举例

1、闭包
  • 代码
def test()
    a = 10
    def inner():
        print(a)
  • a的作用域在整个闭包函数test内, 所以inner中可以访问
def test()
    a = 10
    def inner():
        a = 5
        print(a)
  • 此时在inner中, 定义了一个变量a, 此时inner中的atest中的a, 属于两个不同的变量
  • innerprint(a), 会根据就近原则找到变量a = 5
  • 如果想要inner中的a不是新定义的变量, 而是test中的a进行重新赋值, 需要用到关键字nonlocal
def test()
    a = 10
    def inner():
        nonlocal a
        a = 5
        print(a)
    print(a)
    inner()
    print(a)
test()

# 打印结果:
10
5
5
  • 此时, 使用nonlocal修饰a, 则说明inner中的变量a不是新定义的, 而是test中的, 此时对a赋值, 会修改test中a的值
2、函数中修改全部变量的值
a = 10
def test():
    a = 5
    print(a)
print(a)
test()
print(a)

# 打印结果:
10
5
10
  • 第一次打印, a = 10
  • 第二次打印, 执行了test函数, 在内部新定义了一个变量a = 5
  • 第三次打印, a = 10, 此时打印与第一次相同, 因为在test中没有对全局变量a进行赋值, 而是新定义了一个变量
  • 在函数内部修改全部变量, 与闭包有些类似, 只不过闭包中用的关键字是nonlocal, 而修改全局变量, 则需要使用关键字global
a = 10
def test():
    global a
    a = 5
    print(a)
print(a)
test()
print(a)

# 打印结果:
10
5
5
  • 由于test中的a使用了global关键字进行修饰, 此时a = 5不在是定义新的变量, 而是对全局变量进行赋值操作
3、函数中的变量, 只有在调用时才去查找
a = 10
def test():
    print(a)
    print(b)
    
b = 15
test()

# 打印结果:
10
15
  • 上述代码中, btest后定义, 而在test中使用了b
  • 之所以代码正常运行, 是因为只有在test()时, test函数被调用了, 才去查找b的值, 而此时b = 15已经被定义, 所以不会出错