一、装饰器:
1、装饰器定义:
本质是函数,装饰其它函数,就是为其他函数添加附加功能。
@+函数
2、原则:
2.1.不能修改被装饰的函数的源代码
2.2不能修改被装饰的函数的调用方式
import time def timmer(func): def warpper(*args,**kwargs): start_time=time.time() func() stop_time=time.time() print('the func run time is %s' %(stop_time-start_time)) return warpper @timmer def test1(): time.sleep(3) print('in the test1') test1()
3、实现装饰器知识储备
3.1.函数即’变量'
3.2.高阶函数
满足下列条件之一就可成函数为高阶函数
-
某一函数名当做实参传给另一个函数中(在不修改被装饰函数源代码的情况下为其添加功能)
-
函数的返回值包含n个函数名,n>0(不修改函数的调用方式)
高阶函数示范:
def bar(): print 'in the bar' def foo(func): res=func() return res foo(bar)
高阶函数牛x之处:
def foo(func): return func print 'Function body is %s' %(foo(bar)) print 'Function name is %s' %(foo(bar).func_name) foo(bar)() #foo(bar)() 等同于bar=foo(bar)然后bar() bar=foo(bar) bar()
test2(bar()) #传递函数返回值
和test2(bar) #传递的函数地址
3.3.嵌套函数
在一个函数体内定义一个函数,而不是调用一个函数(基于python支持静态嵌套域)
高阶函数+嵌套函数=>>装饰器
函数嵌套示范:
def foo(): def bar(): print 'in the bar' bar() foo() # bar()
局部作用域和全局作用域的访问顺序:
x=0 def grandpa(): # x=1 def dad(): x=2 def son(): x=3 print x son() dad() grandpa()
局部变量修改对全局变量的影响:
y=10 # def test(): # y+=1 # print y def test(): # global y y=2 print y test() print y def dad(): m=1 def son(): n=2 print '--->',m + n print '-->',m son() dad()
3.4匿名函数 lambda 和普通函数一样
calc = lambda x:x*3 print(clac(3)
4.闭包:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是 closure
def counter(start_num=0): count=[start_num] def incr(): count[0]+=1 return count[0] return incr print counter() print counter()() print counter()() c=counter() print c() print c()
5.装饰器进阶
装饰器原理:
import time def timer(func): #timer(test1) def deco(): """ 在返回时调用该函数 :return: """ start_time = time.time() func() #run test1函数 stop_time=time.time() print('the func run time is %s' %(stop_time-start_time)) return deco @timer #test1=timer(test1)运行函数 def test1(): time.sleep(3) print('in the test1') @timer def test2(): time.sleep(3) print('in the test2') # test1() # test2() # deco(test1) #可以实现运行,但改变了test1运行方式 # deco(test2) #可以实现运行,但改变了test2运行方式 # test1=timer(test1) test1() test2() # test2=deco(test2) # test2()
增加参数:
带有参数的,报错:
test2() File "E:/python34foexam/test-decorator.py", line 58, in deco func() #run test1函数 TypeError: test2() missing 1 required positional argument: 'name'
改正,加入参数:
import time def timer(func): #timer(test1) def deco(*args,**kwargs): """ 在返回时调用该函数 :return: """ start_time = time.time() func(*args,**kwargs) #run test1函数 stop_time=time.time() print('the func run time is %s' %(stop_time-start_time)) return deco #返回deco函数内存地址 @timer #test1=timer(test1)运行函数 def test1(): time.sleep(3) print('in the test1') @timer def test2(name): time.sleep(3) print('in the test2') # test1() # test2() # deco(test1) #可以实现运行,但改变了test1运行方式 # deco(test2) #可以实现运行,但改变了test2运行方式 # test1=timer(test1) test1() test2('alex') # test2=deco(test2) # test2()
装饰器应用实例:
装饰器功能:函数超时则终止
# -*- coding: utf-8 -*- from threading import Thread import time class TimeoutException(Exception): pass ThreadStop = Thread._Thread__stop#获取私有函数 def timelimited(timeout): def decorator(function): def decorator2(*args,**kwargs): class TimeLimited(Thread): def __init__(self,_error= None,): Thread.__init__(self) self._error = _error def run(self): try: self.result = function(*args,**kwargs) except Exception,e: self._error =e def _stop(self): if self.isAlive(): ThreadStop(self) t = TimeLimited() t.start() t.join(timeout) if isinstance(t._error,TimeoutException): t._stop() raise TimeoutException('timeout for %s' % (repr(function))) if t.isAlive(): t._stop() raise TimeoutException('timeout for %s' % (repr(function))) if t._error is None: return t.result return decorator2 return decorator @timelimited(2) def fn_1(secs): time.sleep(secs) return 'Finished' if __name__ == "__main__": print fn_1(4)
装饰器终极(高级版):
模拟n个页面,m个需要验证登录的情况,且home()和bbs()需要不同的验证方式
user,passwd='alex','abc123' def auth(func): def wrapper(*args,**kwargs): username = input('Username').strip() password = input('Password').strip() if username == user and password == passwd: print('