python面向对象进阶-闭包

it2024-12-21  12

文章目录

前言1. 函数引用2. 什么是闭包3. 闭包再理解4. 看一个闭包的实际例子闭包思考


前言

学习python的闭包概念


1. 函数引用

先看个函数的引用情况

def test1(): print("--- in test1 func----") # 调用函数 test1() # 引用函数 ret = test1 print(id(ret)) print(id(test1)) # 通过引用调用函数 ret()

运行结果

--- in test1 func---- 1937642892960 1937642892960 --- in test1 func----

可以看出,引用函数,然后调用,和直接调用函数,实际是调用的同一个方法体


2. 什么是闭包

# 定义一个函数 def test(number): # 在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包 def test_in(number_in): print("in test_in 函数, number_in is %d" % number_in) return number + number_in # 其实这里返回的就是闭包的结果 # 注意,这里返回是test_in 函数体的位置,接收这个参数后,可以直接()调用之前写好的test_in方法 # 这里返回不能加上(),加上后就是返回调用test_in函数的返回值,会报错,缺少number_in参数 return test_in # 给test函数赋值,这个20就是给参数number,并且ret指向了test_in这个函数体的位置 ret = test(20) # 注意这里的100其实给参数number_in print(ret(100)) # 注意这里的200其实给参数number_in print(ret(200))

运行结果

in test_in 函数, number_in is 100 120 in test_in 函数, number_in is 200 220

3. 闭包再理解

内部函数对外部函数作用域里变量的引用(非全局变量),则称内部函数为闭包。

def counter(start=0): count = [start] def incr(): count[0] += 1 return count[0] return incr # c1指向 incr的函数体,并保存了外部函数的变量count=[5] c1 = counter(5) print(c1()) # 等价于incr(),又因为之前保存了count变量值,所以调用的时候自带count值,并进行修改 print(c1()) # c2也指向 incr的函数体,并保存了外部函数的变量count=[100] c2 = counter(100) print(c2()) print(c2()) print(c1()) print(c1()) print(c2()) print(c2())

运行结果

6 7 101 102 8 9 103 104

4. 看一个闭包的实际例子

内部函数对外部函数作用域里变量的引用(非全局变量),则称内部函数为闭包。

def line_conf(a, b): def line(x): return a * x + b return line line1 = line_conf(1, 1) # 调用line_conf方法,并因为line1指向了内部函数line,所以a,b的值还保存 line2 = line_conf(4, 5) # 调用line_conf方法,并因为line2指向了内部函数line,所以a,b的值还保存 print(line1(5)) # 调用line函数,并传入x的值 print(line2(5))

运行结果

6 25

这个例子中,函数line与变量a,b构成闭包。在创建闭包的时候,我们通过line_conf的参数a,b说明了这两个变量的取值,这样,我们就确定了函数的最终形式(y = x + 1和y = 4x + 5)。我们只需要变换参数a,b,就可以获得不同的直线表达函数。由此,我们可以看到,闭包也具有提高代码可复用性的作用。 如果没有闭包,我们需要每次创建直线函数的时候同时说明a,b,x。这样,我们就需要更多的参数传递,也减少了代码的可移植性。

闭包思考

1.闭包似优化了变量,原来需要类对象完成的工作,闭包也可以完成 2.由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存

最新回复(0)