python函数作用域与闭包_理解 Python 中的作用域和闭包

未经作者允许,请勿转载,违者必追究责任。

1. 作用域

Python的作用域可以分为四种:

L (Local) 局部作用域

E (Enclosing) 闭包函数外的函数中

G (Global) 全局作用域

B (Built-in) 内建作用域

变量/函数 的查找顺序: L –> E –> G –>B

意思是,在局部找不到的,便去局部外的局部作用域找(例如 闭包),再找不到的就去全局作业域里找,再找不到就去内建作业域中找。

会影响 变量/函数 作用范围的有

函数:def 或 lambda

类:class

关键字:global noglobal

文件:*py

推导式:[],{},()等,仅限Py3.x中,Py2.x会出现变量泄露。

1、赋值在前,引用在后

# ------同作用域内------

name = "MING"

print(name)

# ------不同作用域内------

name = "MING"

def main():

print(name)

2、引用在前,赋值在后(同一作用域内)

print(name)

name = "MING"

# UnboundLocalError: local variable 'name' referenced before assignment

3、赋值在低层,引用在高层

# L -> E -> G -> B

# 从左到右,由低层到高层

def main():

name = "MING"

print(name)

# NameError: name 'name' is not defined

2. 闭包

闭包这个概念很重要噢。你一定要掌握。

在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。其实装饰函数,很多都是闭包。

好像并不难理解,为什么初学者会觉得闭包难以理解呢?

我解释一下,你就明白了。

一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。

你可以看下面这段代码,就构成了闭包。在内函数里可以引用外函数的变量。

def deco():

name = "MING"

def wrapper():

print(name)

return wrapper

deco()()

# 输出:MING

3. 改变作用域

变量的作用域,与其定义(或赋值)的位置有关,但不是绝对相关。 因为我们可以在某种程度上去改变向上的作用范围。

关键字:global 将 局部变量 变为全局变量

关键字:nonlocal 可以在闭包函数中,引用并使用闭包外部函数的变量(非全局的噢)

global好理解,这里只讲下nonlocal。

先来看个例子

def deco():

age = 10

def wrapper():

age += 1

return wrapper

deco()()

运行一下,会报错。

# UnboundLocalError: local variable 'age' referenced before assignment

但是这样就OK

def deco():

age = 10

def wrapper():

nonlocal age

age += 1

return wrapper

deco()()

# 输出:11

其实,你如果不使用 +=、-=等一类的操作,不加nonlocal也没有关系。这就展示了闭包的特性。

def deco():

age = 10

def wrapper():

print(age)

return wrapper

deco()()

# 输出:10

1.5.4 变量集合

在Python中,有两个内建函数,你可能用不到,但是需要掌握它们。

globals() :以dict的方式存储所有全局变量

locals():以dict的方式存储所有局部变量

globals()

def foo():

print("I am a func")

def bar():

foo="I am a string"

foo_dup = globals().get("foo")

foo_dup()

bar()

# 输出

# I am a func

locals()

other = "test"

def foobar():

name = "MING"

gender = "male"

for key,value in locals().items():

print(key, "=", value)

foobar()

# 输出

# name = MING

# gender = male

  • 0
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:游动-白 设计师:我叫白小胖 返回首页
评论

打赏作者

HAR.王帅真

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值