Python局部函数

Python函数内部可以定义变量, 这样就产生了局部变量. Python还支持函数的嵌套定义, 即在函数的内部定义函数, 这样的函数称为局部函数.

  • 和局部变量一样, 默认情况下局部函数只能在其所在函数的作用域内使用;

Example:

# 全局函数
def foo():
    # 局部函数
    def bar():
        print('Hello, world')
    # 调用局部函数
    bar()
# 调用全局函数
foo()

运行结果为:
Hello, world
  • 就如同全局函数返回其局部变量, 就可以扩大该变量的作用域一样, 通过将局部函数作为所在函数的返回值, 也可以扩大局部函数的作用域;

Example:

# 全局函数
def foo():
    # 局部函数
    def bar():
        print('Hello, world')
    # 将局部函数作为返回值
    return bar
# 调用全局函数
f = foo()
# 调用全局函数中的局部函数
f()

运行结果为:
Hello, world

对于局部函数的作用域可以总结为:

  • 如果所在函数没有返回局部函数, 则局部函数的可用范围仅限于所在的函数内部;
  • 如果所在函数将局部函数作为返回值, 则局部函数的作用域就会扩大, 既可以在所在函数内部使用, 也可以在所在函数的作用域中使用.

另外值得一提的是, 如果局部函数中定义有和其所在的函数中变量同名的变量, 也会发生”遮蔽”问题.

Example:

def foo():
    msg = 'foo'

    def bar():
        print(msg)
        msg = 'bar'

    bar()

foo()

运行上面的代码,报错:

UnboundLocalError: local variable 'msg' referenced before assignment

导致该错误的原因是:

局部函数bar()中定义的msg变量”遮蔽”了所在函数foo()中定义的msg变量. 再加上bar()函数中msg变量的定义在print(msg)语句之后, 违反了先定义后使用的原则, 因此程序报错.

在这里, 由于foo()函数定义的msg变量也是局部变量, 因此这里不能使用globals()函数或者global关键字. 这里可以使用Python提供的nonlocal关键字, 在局部函数中声明一个变量为外部函数中的变量. 这样, 所有对该变量的操作都是对外部变量的操作(赋值操作不会定义变量, 而是对外部变量的修改).

注意

global关键字一样, 使用nonlocal修饰的变量不能直接赋值, 需要先声明再赋值.

Example:

foo():
    msg = 'foo'
    def bar():
        nonlocal msg
        print(msg)
        msg = 'bar'

    bar()
    print(msg)

foo()

运行结果为:
foo
bar