Python3 函数作用域

一 LEGB

什么是LEGB?

L:local 函数内部作用域
E:enclosing 函数内部与内嵌函数之间
G:global 全局作用域
B:build-in 内置作用域

顺序是什么?

跟名字一样,Python在函数里面的查找分为4种,称之为LEGB,也正是按照这种顺序来查找的。

首先,是local,先查找函数内部
然后,是enclosing,再查找函数内部与嵌入函数之间(是指在函数内部再次定义一个函数)
其次,是global,查找全局
最后,是build-in,内置作用域

实例(Python3.0+):

name = 'wangyw'

def foo():
    name = 'maoj'
    def bar():
        print(name)  # 打印的name时就用到函数作用域,它会找本函数中是否存在此变量,如不存在找上级函数中是否存在,逐级上寻找变量,直到找到变量位置。
    return bar

foo()
a = foo() # 把执行foo()函数得到的return返回值赋值给a,也就是把返回值bar赋值给a
print(a)  # 此时打印的是a(bar)的内存地址
a() # 相当于执行bar()

二 函数变量

我们通常把定义在函数外的变量成为全局变量,定义在函数内的变量称为局部变量,顾名思义,全局变量的作用域是整个代码段,局部变量的作用域就只是在它所属的代码段,变量只在它的作用域里有效。 

通过实例,我们可以进一步理解下,全局和局部的概念。

实例1(Python3.0+):

count = 10  # 全局变量

def print_local():
    count = 5  # 局部变量,这个count覆盖了全局变量count,这2个是不同的变量。
    print(count)

def print_global():
    print(count)  # 这里的count是最上面的全局变量噢

print_local()
print_global()

"""
运行结果:
>> 5
>> 10
"""

global

  • 函数中引用修改全局变量

实例(Python3.0+):

count = 10
def foo():
    global count # 告知程序count是全局变量
    print(count)
    count = 7   # 修改全局变量count的值
    print(count)

foo()

"""
运行结果:
>> 10
>> 7
"""

nonlocal

  • 引用修改父级局部变量

实例(Python3.0+):

count = 100

def foo():
    count = 10
    
    def inter():
        nonlocal count
        # 引用父级局部变量
        print(count)
        count = 20
        print(count)
    inter()
    print(count)
    
foo()

"""
运行结果:
>> 10
>> 20
>> 20
"""

小结:

  • 变量查找顺序:LEGB,作用域局部>外层作用域>当前模块中的全局>Python内置作用域。
  • 只有模块、类以及函数才能引用新作用域。
  • 对于一个变量,内部作用域声明会覆盖外部变量,不直接声明,就会使用外部作用域的变量。
  • 内部作用域要修改外部作用域变量的值时,全局变量要使用golbal关键字,嵌套作用域变量要使用nonlocal关键字,nonlocal是Python3新增的关键字,有了这个关键字,就能完美的实现闭包了。
  • 如果函数的内容中无global关键字,优先读取局部变量;如无局部变量,则读取全局变量,但无法对全局变量进行重新赋值(name="ffff"),对于可变类型(列表,字典),可以对内部元素进行操作。

错误实例1:

name = "lvcm"

def count():
    print(name)
    name = "wangyw"
    print(name)

count()

"""
运行结果:
>> UnboundLocalError: local variable 'name' referenced before assignment
"""

错误实例1,函数中没有使用global关键字,print(name),读取的是全局变量name,不能对全局变量name进行修改,但如果name是可变类型(字典,列表)时,可以对全局变量进行修改操作。

实例:

name = ['zhubj','age']

def count():
    print(name)
    name.append("wangyw")
    # 列表的所有方法都可以使用
    print(name)

count()
print(name)
            

"""
运行结果:
>>> ['zhubj', 'age']
>>> ['zhubj', 'age', 'wangyw']
>>> ['zhubj', 'age', 'wangyw']
"""

错误实例2:

name = ['name','age']

def count():
    name = "wangyw"
    global name
    print(name)

count()

"""
运行结果:
>>> SyntaxWarning: name 'name' is assigned to before global declaration global name

备注:函数中使用global声明全局变量时,global之前不能定义与全局变量同名的局部变量,否则会报错。为了避免报错,代码中全局变量使用大写,局部变量使用小写
"""

 

posted @ 2018-06-26 17:00  迷鸟归林  阅读(313)  评论(0编辑  收藏  举报