晓夏

YoungCheung

Zhang Sir's technical way

Python之装饰器

浏览量:880

一、装饰器

1.1 定义

        本质是函数,用来装饰其他函数,就是为其他函数添加附加功能

1.2 原则

       A. 不能修改被装饰的函数的源代码

    B. 不能修改被装饰的函数的调用方式

1.3 实现装饰器

      A. 函数即“变量”

      B. 高阶函数

            a. 把一个函数名当做实参传给另一个函数

       b. 返回值中包含函数名(不修改函数的调用方式)

    C. 嵌套函数

高阶函数+嵌套函数=>装饰器

先来个比喻:

    内裤可以用来遮羞,但是到了冬天它没法为我们防风御寒,聪明的人们发明了长裤,有了长裤后宝宝再也不冷了,装饰器就像我们这里说的长裤,在不影响内裤作用的前提下,给我们的身子提供了保暖的功效。

        再回到我们的主题, 装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

示例:

import time
def timmer(func):
    def func2(*args,**kwargs):
        start_time=time.time()
        func()
        stop_time=time.time()
        print("in the func2 time is %s" %(stop_time-start_time))
    return func2
    
@timmer
def func():
  time.sleep(3)
  print("in the func")
func()

内容详解

函数调用顺序:其他高级语言类似,Python 不允许在函数未声明之前,对其进行引用或者调用
错误示范1:

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

错误示范2:

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

错误:执行foo时还没执行到bar定义

正确示范:(注意,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()

输出结果:

in the foo
in the bar
in the foo
in the bar

装饰器讲解:

1、小高潮

import time
def timmer(function):  #timer(test1)  function=test1
    def deco():
         start_time=time.time()
         function()
         stop_time=time.time()
         print("in the func time is %s" %(stop_time-start_time))
    return deco

@timmer
def  test1():
    time.sleep(3)
    print("in the test1")

def  test2():
    time.sleep(3)
    print("in the test2")
test1()
test2()

输出结果

in the test1
in the func time is 3.000171661376953
in the test2

2.中高潮

import time
def timmer(function):  #timer(test1)  function=test1
    def  deco(*args,**kwargs):
         start_time=time.time()
         function(*args,**kwargs)
         stop_time=time.time()
         print("in the func time is %s" %(stop_time-start_time))
    return deco
@timmer  # test1=timmer(test1) == deco  test2(name) = deco(name)
def  test1():
    time.sleep(1)
    print("in the test1")
    
@timmer   # test1=timmer(test2)
def  test2(name,age):
    time.sleep(5)
    print("test2 is ",name,age)
test1()
test2("youngcheung",22)

3.终极版

import time
user,passwd='root','123'
def auth(auth_type):
    print("auth function",auth_type)
    def outer_wrapper(function):
        def wrapper(*args,**kwargs):
            print("auth function 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 authention\033[0m")
                    res = function(*args,**kwargs)
                    print("---after authentication")
                    return res
                else:
                    exit("\033[31;1mInvalid username or password\033[0m")
            elif auth_type == 'ldap':
                print("不会")
        return wrapper
    return outer_wrapper
def index():
    print("welcome to index page")
@auth(auth_type="local")
def home():
    print("welcome to home page")
    return "from home"
@auth(auth_type="ldap")
def bbs():
    print("welcome to bbs page")
index()
print(home())
bbs()


神回复

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。