一,装饰器(decorator)。(day4.3)
装饰器:本质是函数,(装饰其他函数)就是为其他函数添加附加功能。
#可以达成的作用# 原则1:不能修改被装饰的函数的源代码。(改源代码有可能会造成未知的错误,因为你不知道有些地方是怎么样调用此函数的)
#可以达成的作用# 原则2:不能修改被修饰的函数的调用方式。(即,不对原函数照成任何影响)
1.实现装饰器的知识储备:
1.函数即”变量“。
2.高阶函数。
3.嵌套函数。
高阶函数+嵌套函数=装饰器
===》》》1.函数即“变量”(要重点理解这个)
a).内存存储回收机制(解释器源代码可知其底层实现方式)==》》D4.5.-+11:54
若没有变量名/函数名也就是说没有地方引用这边内存,在解释器刷新的时候这片内存则会被回收。
b)函数在内存里的存放机制是:(仅仅写一个函数名则相当于这个函数体所占用的内存地址,而内存地址加上小括号则相当于运行这个内存地址里的”东西“
可以理解为()就是执行这个它前面的内存地址里的东西的执行动作)
#实例
#return 后的值是函数运行完成后返回到开始运行处的“东西”
import time def bar(): time.sleep(0.5) print("in the bar") return 123 print(bar()) t = bar print(bar) t()
用函数名即def后的为“门牌号”找到一个内存地址再将函数体存入这个内存中。等待使用这个门牌号(即函数名)来调用他对应的内存里的函数体来执行。
===》》》2.高阶函数:
a)把一个函数名当实参传给另一个函数。(可实现,在不修改被装饰的函数的源代码情况下为其添加功能)
#高阶函数的a)功能实例。
import time
def bar():
time.sleep(3)
print("in the bar")
def funt1(funt):
# start_time = time.time()
print('hello world!')
return funt
bar = funt1(bar)
bar()
b)返回值中包含函数名。(不修改被修饰的函数的调用方式,对原函数添加了功能。)
import time def bar(): time.sleep(0.5) print("in the bar") # def test2(name): # print(name) # return name # print(test2(bar)) def time1(funt): start_time = time.time() funt() end_time = time.time() print('该程序运行时间是:%s'%(start_time-end_time)) return funt bar = time1(bar) bar() #不修改被修饰的函数的调用方式,对原函数添加了功能。
===》》》3.嵌套函数。
函数里套一个被定义的函数
#实例 def test1(): print("AAA") def test2():#嵌套函数只能在这个局部语句块里使用,函数即变量和局部变量同理。 pass
#下面的实例可以演示函数的局部性
def test1():
x = 'h'
def test2():
x = 'h1'
def test3():
x ='h2'
print(x)
test3()
test2()
test1()
》》》h2
def test1():
x = 'h'
def test2():
x = 'h1'
def test3():
# x ='h2'
print(x)
test3()
test2()
test1()
》》》h1
def test1():
x = 'h'
def test2():
# x = 'h1'
def test3():
# x ='h2'
print(x)
test3()
test2()
test1()
》》》h
2.最简单的装饰器实例:
def timer(func):
def deco():
import time
start_time=time.time()
func()
stop_time=time.time()
print('the func run time is %s'%(start_time-stop_time))
return deco
def test():
import time
print('start')
time.sleep(1)
print('stop')
test()
》》》start
stop
test=timer(test)
test()
》》》start
stop
the func run time is -1.0072598457336426
小节:装饰器是在被装饰的函数头加上@timer即相当于 在使用的时候写了一个test=timer(test)
def timer(func):
def deco():
import time
start_time=time.time()
func()
stop_time=time.time()
print('the func run time is %s'%(start_time-stop_time))
return deco
@timer
def test():
import time
print('start')
time.sleep(1)
print('stop')
test()
》》》 start
stop
the func run time is -1.0072598457336426
3.装饰器升级,可以修饰随便几个参数的函数,并且可以返回被装饰函数的返回值。
def timer(func):
def deco(*args,**kwargs): #修饰随便几个参数的函数
import time
start_time=time.time()
ret=func(*args,**kwargs) #修饰随便几个参数的函数
stop_time=time.time()
print('the func run time is %s'%(start_time-stop_time))
return ret #返回被装饰函数的返回值
return deco
@timer
def test():
import time
print('start')
time.sleep(1)
print('stop')
@timer #相当于加了一条test1=timer(test1)
def test1(name,age):
print('123',name,age)
test()
test1(123,22)
4.最终完整版,装饰器。(包含了说明)#51cto博客有相关内容#
# Author:979 # blog addr:http://www.cnblogs.com/home979/ user ="zsw" code ="123" def auth(aut_type): #print(aut_type)#可以了解传入装饰器的aut_type参数是什么量 def choice(func): #print(func)#可以了解传入装饰器的func参数是什么量 def yanzhen(*args,**kwargs): #print(*args,**kwargs)#可以了解传入装饰器的*args,**kwargs参数是什么量 if aut_type =='local':#这一句是装饰器type:local的具体功能 username = input("username:") password = input("password:") if user == username and code == password: print("waiting") # ret = func(*args,**kwargs) #这样的话可以得到func的返回值 并且可以继续运行 # return ret #直接用这样一句就可以返回开始得到func的返回值 return func(*args,**kwargs) #可用上面两句替换,这一句必须加 else: print("Invalid username or password") elif aut_type =='ldap':#这一句是装饰器type:ldap的具体功能 print("不会弄ldap,搞毛线啊") return yanzhen#返回yanzhen的物理地址 return choice #返回choice的物理地址 #下面是具体被调用装饰器的函数实例 def index(): print("welcom to index") @auth(aut_type='local') def home(bankuai): if bankuai =='home': print("welcom to home A") else: print("welcom to home B") return "from 123" @auth(aut_type='ldap') def bbs(): print("welcom to bbs") index() print(home('home')) bbs()
二,匿名函数:
没有def申明函数名字。
例如: 匿名函数
lambda n:print(n)
相对于
def dayin(n):
print(n)
这个函数