Python基礎4 裝飾器

python裝飾器python

一:函數調用順序:其餘高級語言相似,Python 不容許在函數未聲明以前,對其進行引用或者調用
錯誤示範:
shell

def foo():
    print 'in the foo'
    bar()
     
foo()
 
報錯:
in the foo
 
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    foo()
  File "<pyshell#12>", line 3, in foo
    bar()
NameError: global name 'bar' is not defined

def foo():
    print 'foo'
    bar()
foo()
def bar():
    print 'bar'
     
報錯:NameError: global name 'bar' is not defined


正確示範:(注意,python爲解釋執行,函數foo在調用前已經聲明瞭bar和foo,因此bar和foo無順序之分)
閉包

def bar():
    print 'in the bar'
def foo():
    print 'in the foo'
    bar()
     
foo()
 
def foo():
    print 'in the foo'
    bar()
def bar():
    print 'in the bar'
foo()


二:高階函數
app

知足下列條件之一就可成函數爲高階函數ide

  1. 把一個函數名當作實參傳給另一個函數(在不修改被裝飾器函數源代碼的狀況下爲其添加功能)函數

  2. 函數的返回值包含n個函數,n>0(不修改函數的調用方式)spa

高階函數示範:code

def bar():
    print 'in the bar'
def foo(func):
    res=func()  #res=func()=bar()
    return res  #返回函數執行的結果
foo(bar) #執行函數foo(bar),把bar函數做爲參數傳入


高階函數的牛逼之處:內存

def bar():
    time.sleep(3)
    print('in the bar')
    
def foo(func):
    return func  #返回函數的內存地址
 
print(foo(bar)) #打印出函數bar的內存地址
foo(bar)()      #執行foo(func)函數
bar=foo(bar)    #賦值給變量bar,在python中裝飾器使用@foo代替
bar()           #執行變量bar()函數


三:內嵌函數和變量做用域utf-8

定義:在一個函數體內建立另一個函數,這種函數就叫內嵌函數(基於python支持靜態嵌套域)

在一個函數的函數體內,用def聲明一個函數,而不是調用一個函數

函數嵌套示範:

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()


四:閉包:若是在一個內部函數裏,對在外部做用域(但不是在全局做用域)的變量進行引用,那麼內部函數就被認爲是 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()


五:內嵌函數+高階函數+閉包=》裝飾器

裝飾器:
定義:本質是函數,(裝飾其它函數)就是爲其它函數添加附加功能
原則:

1.不能修改被裝飾的函數的源代碼

2.不能修改被裝飾的函數的調用方式         


預熱兩個範例:

範例一:函數參數固定

def decorartor(func):
    def wrapper(n):
        print('starting')
        func(n)
        print('stopping')
    return wrapper  # 執行decorartor函數,返回wrapper函數內存地址

def test(n):
    print('in the test arg is %s' % n)

decorartor(test)('alex')  
#decorartor(test) 等於  return wrapper函數內存返回值
#decorartor(test)(alex) = wrapper(alex) 執行函數
#decorartor(test)(alex):func等於函數名,n等於上面函數名帶的參數


範例二:函數參數不固定

def decorartor(func):
    def wrapper(*args,**kwargs):
        print 'starting'
        func(*args,**kwargs)
        print 'stopping'
    return wrapper
 
 
def test(n,x=1):
    print 'in the test arg is %s' %n
 
decorartor(test)('alex',x=2)

1.無參裝飾器

import time
def decorator(func):   #decorator(test) func=test
        def wrapper(*args,**kwargs):
            start=time.time()
            func(*args,**kwargs) #run test()
            stop=time.time()
            print 'run time is %s ' %(stop-start)
            print timeout
        return wrapper  #返回一個變量的內存地址
 
@decorator #至關於test=decorator(test)=wrapper  test()=wrapper()"執行wrapper變量"
def test(list_test):
    for i in list_test:
        time.sleep(0.1)
        print '-'*20,i
  
 
#decorator(test)(range(10)) 
test(range(10))

2.有參裝飾器

import time
def timer(timeout=0):
    def decorator(func):
        def wrapper(*args,**kwargs):
            start=time.time()
            func(*args,**kwargs)
            stop=time.time()
            print 'run time is %s ' %(stop-start)
            print timeout
        return wrapper
    return decorator
@timer(2)
def test(list_test):
    for i in list_test:
        time.sleep(0.1)
        print '-'*20,i
  
#timer(timeout=10)(test)(range(10))
test(range(10))


六:裝飾器應用案例:

裝飾器功能:函數超時則終止

# -*- 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)
相關文章
相關標籤/搜索