Python学习(19):函数式编程-闭包的使用

时间:2022-12-30 22:41:09

一、函数也是对象

Python里一切皆是对象,函数也可以当做一个对象来使用

def func1():
    print("这是一个函数")
print(type(func1)) #打印:<class 'function'>

此处说明函数也是一个类型,也可以当做对象来使用

二、函数中的函数:闭包

闭包:函数+环境变量(如下例中的func_in和a)

def func_out():
    a = 10
    def func_in(x):
        result = a*x + 100
        print("func_in的计算结果是:" + str(result))
    return func_in

a = 20    
f = func_out()
f(2)   #打印出120而不是140

理解:func_in与a构成了一个闭包,通过func_out()返回的f得到的是带有环境变量的闭包;
即使a在外界改变了,但是依然不会改变f的闭包环境

打印闭包的中的内容:

#1.打印闭包的环境变量
print(f.__closure__)
#打印:(<cell at 0x108ef71f8: int object at 0x108b7fba0>,)

#2.打印闭包的环境变量的值
print(f.__closure__[0].cell_contents)
#打印:10

三、使用闭包的误区

def func1():
    a = 10
    def func2():
        a = 20 #此时a是局部变量,不会影响外部变量
        print(a)  
    print(a)
    func2()
    print(a)
    return funky

#1.查看a值的变化,打印结果如下:
func1()
''' 10 20 10 '''

#2.func2并不是一个闭包
f = func1()
print(f.__closure__)
#此出打印None,说明func2并不是一个闭包,因为在func2内部使用了局部变量a,没有成功引用外部环境中变量a

达不到形成闭包的条件:缺少闭包环境变量

四、闭包的引用

闭包可以携带函数环境,所以可以利用这一特征避免大量使用全局变量,下面就是一个应用的示例:
模拟一个问题:计算用户累计量sum,初始sum= 0,以后每天增加不定新用户数num,每次新增用户后可以查看新的用户总数sum

1.使用非闭包方法来解决

sum = 0
def count(num):
    global sum 
    newSum = sum + num #代码1
    sum = newSum   #代码2
    return sum
print(count(2))
print(count(4))
print(count(6))
#如果不使用global,此例报错:local variable 'sum' referenced before assignment;

分析代码:这是因为定义count函数的时候,代码2中的sum出现在等号左边,Python会将其视为局部变量而不会再在外部寻找sum变量,而在代码执行时,由于代码1在代码2之前,代码1中的sum找不到定义,所以报错
解决方法:在代码1前添加: global sum

2.使用闭包解决

sum1 = 0
def factory(current):
    def count(num):
        nonlocal current #添加nonlocal,说明current不是局部变量
        newCount = current + num
        current = newCount
        return newCount
    return count
func = factory(sum1)
print(func(2))
print(func(4))
print(func(6))
print(sum1)   #打印出0,其实sum1并没有被用到