八、函数、闭包、装饰器
一、函数对象
一、函数对象:把函数的内存地址当作一种变量值去使用
1、引用
def func1():
print('from func')
#func1=函数的内址
func2=func1
func2()
2、可以当作参数传给另外的函数
3、可以当作一个函数的返回值
4、可以当作容器类型的元素
二、名称空间与作用域
1. 什么是名称空间namespaces
存放名字与值内存地址绑定关系的地方
2. 为何要有名称空间
3. 如何用名称空间
内置名称空间
全局名称空间
局部名称空间
4. 总结结论:
1. 查找名字的顺序是从当前位置往外查找
2. 名称空间的嵌套关系是在函数定义阶段就固定死的,与调用位置无关
二、闭包
1. 什么是闭包函数
闭函数: 该函数一定是定义在函数内的函数
包函数: 该内部函数包含对外层函数作用域名字的引用
def outter():
x=111
def inner():
print(x)
return inner
f=outter()
x=22222
f()
2. 为何要用闭包函数
3. 如何用
4、为函数体传值的方案一: 直接以参数的形式传入
为函数体传值的方案二:闭包传值
三、装饰器
1. 什么是装饰器
装饰器指的是为被装饰对象添加新功能的工具
装饰器本身可以是任意可调用对象
被装饰对象本身也可以是任意可调用对象
2. 为何要用装饰器
开放封闭原则:对修改封闭,对扩展开发
装饰器的实现原则:
1. 不能修改被装饰对象的源代码
2. 不能修改被装饰对象的调用方式
装饰器的目的:
就是在遵循原则1和2的前提为被装饰对象添加新功能
3. 如何用
eg:
def outter(func):
# func=index
def wrapper(*args, **kwargs): # 被装饰的函数可带参
start_time = time.time()
func(*args, **kwargs)
stop_time = time.time()
res = stop_time - start_time
return res
return wrapper
@outter # index=outter(index) #outter(index) = wrapper #wrapper = 添加的功能 + index
def index():
time.sleep(1)
print('welcome index page')
@outter
def home(name):
time.sleep(2)
print('welcome home page')
print(name)
res1 = index() # index=outter(index)=wrapper的内存地址 res1=wrapper()
print(res1) # 获取wrapper()函数的返回值是res
res2 = home('egon')
print(res2)
4、叠加多个装饰器
1. 加载顺序(outter函数的调用顺序):自下而上
2. 执行顺序(wrapper函数的执行顺序):自上而下
def outter1(func1): #func1=wrapper2的内存地址
print('加载了outter1')
def wrapper1(*args,**kwargs):
print('执行了wrapper1')
res1=func1(*args,**kwargs)
return res1
return wrapper1
def outter2(func2): #func2=wrapper3的内存地址
print('加载了outter2')
def wrapper2(*args,**kwargs):
print('执行了wrapper2')
res2=func2(*args,**kwargs)
return res2
return wrapper2
def outter3(func3): # func3=最原始的那个index的内存地址
print('加载了outter3')
def wrapper3(*args,**kwargs):
print('执行了wrapper3')
res3=func3(*args,**kwargs)
return res3
return wrapper3
@outter1 # outter1(wrapper2的内存地址)======>index=wrapper1的内存地址
@outter2 # outter2(wrapper3的内存地址)======>wrapper2的内存地址
@outter3 # outter3(最原始的那个index的内存地址)===>wrapper3的内存地址
def index():
print('from index')
print('======================================================')
index()
5、有参装饰器
import time
current_user={'user':None}
def outter(func):
def wrapper(*args,**kwargs):
if current_user['user'] is not None:
res=func(*args,**kwargs)
return res
user=input('username>>>: ').strip()
pwd=input('password>>>: ').strip()
if user == 'egon' and pwd == '123':
print('login successfull')
current_user['user']=user
res=func(*args,**kwargs)
return res
else:
print('user or password error')
return wrapper
@outter
def index():
time.sleep(1)
print('from index')
@outter
def home(name):
print('welcome %s' %name)
index()
home('egon')
6、三元表达式
def max2(x,y):
if x > y:
return x
else:
return y
res=max2(10,20)
x=10
y=20
# res=x if x > y else y
# print(res)
res='OK' if False else 'No'
print(res)
7、生成式
列表生成式
l=[]
for i in range(10):
if i > 4:
l.append(i**2)
l=[i**2 for i in range(10) if i > 4]
print(l)
names=['egon','alex_sb','kevin_sb','hxx_sb','cxx_sb']
sbs=[]
for name in names:
if name.endswith('sb'):
sbs.append(name)
sbs=[name.upper() for name in names if name.endswith('sb')]
print([name.upper() for name in names])
print([name for name in names if name.endswith('sb')])
字典生成式
res={i:i**2 for i in range(10) if i > 3}
print(res)
print({i for i in 'hello'})
8、匿名函数
# def func():
# print('from func')
#
#
# func()
# func()
# func()
# 匿名函数就是只定义了一个函数的内存地址,主要用于临时使用一次的场景
# func=lambda x,y:x+y
# print(func)
# print(func(1,2))
# res=(lambda x,y:x+y)(1,2)
# print(res)
# print(max([10,11,-3,23]))
salaries={
'egon':3000,
'alex':100000000,
'wupeiqi':10000,
'yuanhao':2000
}
# def func(k):
# return salaries[k]
# print(max(salaries,key=lambda k:salaries[k]))
# print(min(salaries,key=func))
# for循环的结果 比较依据
# 'egon' 3000
# 'alex' 100000000
# 'wupeiqi' 10000
# 'yuanhao' 2000
# l=[4,2,3]
# l_new=sorted(l,reverse=True)
# print(l_new)
print(sorted(salaries,key=lambda k:salaries[k],reverse=True))