
一、函数对象
精髓:可以把函数当成变量去用
# func=内存地址
def func():
print('from func')
# 1、可以赋值
f=func
print(f,func) # 同一个内存地址
f() # --》 func()
# 2、可以当做参数传给另外一个函数
def foo(x): # x = func的内存地址
print(x) # func的内存地址
x() # func()
foo(func) # foo(func的内存地址)
# 3、可以当做另外一个函数的返回值
def foo(x): # x=func的内存地址
return x # return func的内存地址
res=foo(func) # foo(func的内存地址)
print(res) # res=func的内存地址
res() # func()
# 4、可以当做容器类型的一个元素
l=[func,]
print(l) # func的内存地址
l[0]()
dic={'k1':func}
print(dic)
dic['k1']()
二、函数嵌套
# 作用:隐藏代码在函数体内,外部无法看见这段代码
# 1、函数的嵌套调用:在调用一个函数的过程中又调用其他函数
def max2(x,y):
if x > y:
return x
else:
return y
def max4(a,b,c,d):
# 第一步:比较a,b得到res1
res1=max2(a,b)
# 第二步:比较res1,c得到res2
res2=max2(res1,c)
# 第三步:比较res2,d得到res3
res3=max2(res2,d)
return res3
res=max4(1,2,3,4)
print(res)
# 2、函数的嵌套定义:在函数内定义其他函数
def f1():
def f2():
pass
# 圆形
def circle(radius,action=0):
from math import pi
# 求圆形的求周长:2*pi*radius
def perimiter(radius):
return 2*pi*radius
# 求圆形的求面积:pi*(radius**2)
def area(radius):
return pi*(radius**2)
if action == 0:
return 2*pi*radius
elif action == 1:
return area(radius)
circle(33,action=0)
三、闭包函数
1、大前提:
# 闭包函数:名称空间与作用域+函数嵌套+函数对象
核心点:名字的查找关系是以函数定义阶段为准
2、什么是闭包函数
"闭"函数指的该函数是内嵌函数(是定义在其他函数内的函数)
"包"函数指的该函数包含对外层函数作用域名字的引用(不是对全局作用域)
# 定义:
若内嵌函数包含对外部函数作用域(而非全局作用域)中变量的引用,
那么该’内嵌函数’就是闭包函数,简称闭包(Closures)
# 因而无论在何处调用闭包函数,使用的仍然是包裹在其外层的变量。
# 下例中 f2 包含了 对 f1 的局部名称
# 闭包函数:名称空间与作用域的应用+函数嵌套
def f1():
x = 33333333333333333333
def f2():
print(x)
f2()
x=11111
def bar():
x=444444
f1() # 33333333333333333333
def foo():
x=2222
bar()
foo() # 33333333333333333333
# 闭包函数:函数对象
def f1():
x = 33333333333333333333
def f2():
print('函数f2:',x)
return f2
f=f1() # f2
# print(f)
x=4444
f() # 函数f2: 33333333333333333333
def foo():
x=5555
f()
foo() # 函数f2: 33333333333333333333
3、为何要有闭包函数
===》闭包函数的应用
# 两种为函数体传参的方式
# 方式一:直接把函数体需要的参数以参数(形参)的形式传入
def f2(x):
print(x)
f2(1)
f2(2)
f2(3)
# 方式二:利用名称空间与作用域的功能 将值包给函数,从外部函数中的名称空间获取
def f1(x): # x=3
# x=3
def f2():
print(x)
return f2
x=f1(3)
print(x) # f2的内存地址
x() # 3
# 重点:
若是一个函数无法直接给它传参,可考虑将其写成闭包函数,通过外部函数传参
import requests
# 传参的方案一:
def get(url):
response=requests.get(url)
print(len(response.text))
get('https://www.cnblogs.com/linhaifeng')
get('https://www.cnblogs.com/linhaifeng')
get('https://zhuanlan.zhihu.com/p/109056932')
# 传参的方案二:
def outter(url):
# url='https://www.baidu.com'
def get():
response=requests.get(url)
print(len(response.text))
return get
cnblogs=outter('https://www.cnblogs.com/linhaifeng')
cnblogs()
cnblogs()
zhihu=outter('https://zhuanlan.zhihu.com/p/109056932')
zhihu()
# 对比两种方式
方式一在下载同一页面时需要重复传入url,
方式二只需要传一次值,就会得到一个包含指定url的闭包函数,以后调用该闭包函数无需再传url
# 注:闭包函数的这种特性有时又称为惰性计算。使用将值包给函数的方式,在接下来的装饰器中也将大有用处