一、函数也是对象
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并没有被用到