<commit_before>---
layout: article
title:  "装饰器总结"
categories: python
toc: true
ads: true
image:
    teaser: /teaser/decorator.jpg
---

> 由于函数也是一个对象，而且函数对象可以被赋值给变量，所以，通过变量也能调用该函数。  

---


## 1.概念
装饰器:(器：函数)，本质就是函数，用来装饰器其他函数，为代码运行期间动态增加功能的方式。  

## 2.原则：
- 不能修改被装饰函数的源代码  
- 不能修改被装饰函数的调用方式  

## 3.例子
需求：打印出函数test1的执行时间   

~~~ python
#-*- coding: utf-8 -*-
__author__ = "xtrdb.net"

import time

def test2(func):

    '''
    高阶函数
    '''
    
    def test3():

        '''
        嵌套函数

        '''
        start_time = time.time()
        func()
        stop_time = time.time()
        print('run time: %s' %(stop_time - start_time))
    return test3


@test2   # =>  test1 = test2(test1)
def test1():
    time.sleep(1)
    print('in the test1')

test1()

output：
in the test1
run time: 1.0000572204589844
~~~


## 4.实现装饰器(D)的知识储备    
- A.函数即"变量"  
- B.高阶函数  
- C.嵌套函数  
> B + C = D  
理解：  
A: 和变量一样，一样的内存回收机制  
B: 把一个函数当作实参传给另一个函数  
   返回值中包含函数名  
C: 子一个函数体用def定义的函数，扩展：匿名函数   

**匿名函数：**  
当我们在传入函数时，有些时候，不需要显式地定义函数，直接传入匿名函数更方便，      
关键字lambda表示匿名函数，即，函数没有具体的名称，冒号前面的x表示函数参数。    
匿名函数有个限制，就是只能有一个表达式，不用写return，返回值就是该表达式的结果。  
先来看一个最简单例子：     
~~~ python
def f(x):
    return x ** 2

f(3)   ==> 9


使用lambda：
f = lambda x : x**2
print f(3)
~~~
到这里，你再回去看**3.例子**，应该轻而易举的，嘿嘿 ~~    

## 实例
实例一：函数参数固定
~~~ python
# -*- coding: utf-8 -*-
def decorartor(func):
    def wrapper(n):
        print('starting')
        func(n)
        print('stopping')
    return wrapper

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

decorartor(test)('xtrdb')
~~~

实例二：函数参数不固定   
基础版：    
~~~ python
# -*- coding: utf-8 -*-
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,x)

decorartor(test)('xtrdb',8)
~~~  
升级版：    
~~~ python 
# -*- coding: utf-8 -*-
import time
def timer(func): #timer(test1)  func=test1
    def deco(*args,**kwargs):
        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
@timer  #test1=timer(test1)
def test1():
    time.sleep(1)
    print('in the test1')

@timer # test2 = timer(test2)  = deco  test2(name) =deco(name)
def test2(name,age):
    print("test2:",name,age)

test1()
test2("xtrdb",18)
~~~ 
至尊版：    
~~~ python
# -*- coding: utf-8 -*-
import time
user,passwd = '<PASSWORD>','<PASSWORD>'
def auth(auth_type):
    print("auth func:",auth_type)
    def outer_wrapper(func):
        def wrapper(*args, **kwargs):
            print("wrapper func args:", *args, **kwargs)
            if auth_type == "local":
                username = input("Username:").strip()
                password = input("Password:").strip()
                if user == username and passwd == password:
                    print("\033[32;1mUser has passed authentication\033[0m")
                    res = func(*args, **kwargs)  # from home
                    print("---after authenticaion ")
                    return res
                else:
                    exit("\033[31;1mInvalid username or password\033[0m")
            elif auth_type == "ldap":
                print("ldap, will not!")

        return wrapper
    return outer_wrapper

def index():
    print("welcome to index page")
@auth(auth_type="local") # home = wrapper()
def home():
    print("welcome to home  page")
    return "from home"

@auth(auth_type="ldap")
def bbs():
    print("welcome to bbs  page")

index()
print(home()) #wrapper()
bbs()
~~~
## 小结
1.在面向对象（OOP）的设计模式中，decorator被称为装饰模式。OOP的装饰模式需要通过继承和组合来实现，     
而Python除了能支持OOP的decorator外，直接从语法层次支持decorator。Python的decorator可以用函数实现，     
也可以用类实现。

2.decorator可以增强函数的功能，定义起来虽然有点复杂，但使用起来非常灵活和方便。   

3.真正的成功没有捷径可走，所以你，学会在挫折中成长。    <commit_msg>Update 2016-07-10-装饰器.md<commit_after>---
layout: article
title:  "装饰器屌丝总结"
categories: python
toc: true
ads: true
image:
    teaser: /teaser/decorator.jpg
---

> 由于函数也是一个对象，而且函数对象可以被赋值给变量，所以，通过变量也能调用该函数。  

---


## 1.概念
装饰器:(器：函数)，本质就是函数，用来装饰器其他函数，为代码运行期间动态增加功能的方式。  

## 2.原则  
- 不能修改被装饰函数的源代码  
- 不能修改被装饰函数的调用方式  

## 3.例子
需求：打印出函数test1的执行时间   

~~~ python
#-*- coding: utf-8 -*-
__author__ = "xtrdb.net"

import time

def test2(func):

    '''
    高阶函数
    '''
    
    def test3():

        '''
        嵌套函数

        '''
        start_time = time.time()
        func()
        stop_time = time.time()
        print('run time: %s' %(stop_time - start_time))
    return test3


@test2   # =>  test1 = test2(test1)
def test1():
    time.sleep(1)
    print('in the test1')

test1()

output：
in the test1
run time: 1.0000572204589844
~~~


## 4.实现装饰器(D)的知识储备    
- A.函数即"变量"  
- B.高阶函数  
- C.嵌套函数  
> B + C = D  
理解：  
A: 和变量一样，一样的内存回收机制  
B: 把一个函数当作实参传给另一个函数  
   返回值中包含函数名  
C: 子一个函数体用def定义的函数，扩展：匿名函数   

**匿名函数：**  
当我们在传入函数时，有些时候，不需要显式地定义函数，直接传入匿名函数更方便，      
关键字lambda表示匿名函数，即，函数没有具体的名称，冒号前面的x表示函数参数。    
匿名函数有个限制，就是只能有一个表达式，不用写return，返回值就是该表达式的结果。  
先来看一个最简单例子：     
~~~ python
def f(x):
    return x ** 2

f(3)   ==> 9


使用lambda：
f = lambda x : x**2
print f(3)
~~~
到这里，你再回去看**3.例子**，应该轻而易举的，嘿嘿 ~~    

## 5.实例
实例一：函数参数固定
~~~ python
# -*- coding: utf-8 -*-
def decorartor(func):
    def wrapper(n):
        print('starting')
        func(n)
        print('stopping')
    return wrapper

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

decorartor(test)('xtrdb')
~~~

实例二：函数参数不固定   
基础版：    
~~~ python
# -*- coding: utf-8 -*-
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,x)

decorartor(test)('xtrdb',8)
~~~  
升级版：    
~~~ python 
# -*- coding: utf-8 -*-
import time
def timer(func): #timer(test1)  func=test1
    def deco(*args,**kwargs):
        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
@timer  #test1=timer(test1)
def test1():
    time.sleep(1)
    print('in the test1')

@timer # test2 = timer(test2)  = deco  test2(name) =deco(name)
def test2(name,age):
    print("test2:",name,age)

test1()
test2("xtrdb",18)
~~~ 
至尊版：    
~~~ python
# -*- coding: utf-8 -*-
import time
user,passwd = '<PASSWORD>','<PASSWORD>'
def auth(auth_type):
    print("auth func:",auth_type)
    def outer_wrapper(func):
        def wrapper(*args, **kwargs):
            print("wrapper func args:", *args, **kwargs)
            if auth_type == "local":
                username = input("Username:").strip()
                password = input("Password:").strip()
                if user == username and passwd == password:
                    print("\033[32;1mUser has passed authentication\033[0m")
                    res = func(*args, **kwargs)  # from home
                    print("---after authenticaion ")
                    return res
                else:
                    exit("\033[31;1mInvalid username or password\033[0m")
            elif auth_type == "ldap":
                print("ldap, will not!")

        return wrapper
    return outer_wrapper

def index():
    print("welcome to index page")
@auth(auth_type="local") # home = wrapper()
def home():
    print("welcome to home  page")
    return "from home"

@auth(auth_type="ldap")
def bbs():
    print("welcome to bbs  page")

index()
print(home()) #wrapper()
bbs()
~~~
## 6.小结
1.在面向对象（OOP）的设计模式中，decorator被称为装饰模式。OOP的装饰模式需要通过继承和组合来实现，     
而Python除了能支持OOP的decorator外，直接从语法层次支持decorator。Python的decorator可以用函数实现，     
也可以用类实现。

2.decorator可以增强函数的功能，定义起来虽然有点复杂，但使用起来非常灵活和方便。   

3.真正的成功没有捷径可走，所以你，学会在挫折中成长。    
{'fraction_non_alphanumeric': 0.15852713178294572, 'fraction_numerical': 0.023772609819121448, 'mean_word_length': 2.6038175046554937, 'pattern_counts': {'":': 4, '<': 7, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1868633', 'n_tokens_mistral': 3624, 'n_tokens_neox': 3746, 'n_words': 585}