Python之装饰器

装饰器学习

一、装饰器

1、什么是装饰器

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

2、装饰器原则

a、不修改被装饰函数的源代码;

b、不修改被装饰函数的调用方式;

c、不能违反开放封闭原则:程序一旦上线,不能更改内部源代码,一旦更改程序内部源代码,就可能产生问题;

3、装饰器的知识储备

装饰器=高阶函数+函数嵌套+闭包

(1)、高阶函数定义

a、函数接收的参数是一个函数

b、函数的返回值是一个函数;

c、满足上面条件中的任意条件都可称之为高阶函数;

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
#使用高阶函数为函数foo添加一个统计运行时间的功能;
##功能已经实现,没有违反修改程序源代码,没有违反函数调用方式;
#但是从运行结果来看,程序运行了两遍,该方法不行;
import time
def foo():
    time.sleep(3)
    print("来自foo函数")
def timer(func):
    start_time = time.time()
    func()
    end_time = time.time()
    print("函数%s的的运行时间为:%s" %(func,end_time-start_time))
    return func
foo = timer(foo)
foo()     
"""
来自foo函数
函数<function foo at 0x0000022DDB7729D8>的的运行时间为:3.008920431137085
来自foo函数
"""

 (2)、函数嵌套

函数内部调用函数不表函数嵌套,函数内部重新定义了一个函数叫函数嵌套;

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
###这不是函数嵌套
import time
def foo():
    time.sleep(3)
def bar():
    print("来自bar函数")
    foo()
    print("当前时间为:%s" %time.time())
bar()

 上面的函数不是函数嵌套

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import time
def bar():
    print("来自bar函数")
    def foo():
        time.sleep(3)
    print("当前时间为:%s" %time.time())
bar()

 这才是函数嵌套

(3)、函数闭包

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
def father(name):
    print("来自father函数")
    def son():
        print("我的爸爸是%s" %name)
        def grandson():
            name = "就是我自己"
            print("我的爷爷是%s" %name)
        grandson()
    son()
father("尼古拉斯赵四")

 

 函数闭包其实函数作用域

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import time
def test():
    time.sleep(3)
    print("test函数运行完毕")
def timer(func):
    def wrapper():
        start_time = time.time()
        func()
        end_time = time.time()
        print("函数func的运行时间为:%s" %(end_time-start_time))
    return wrapper
test = timer(test)
test()
"""输出结果:
test函数运行完毕
函数func的运行时间为:3.02397084236145

"""
#备注:a、没有修改程序内部代码;b、没有修改程序的调用方式;
#完成了为程序添加附加功能

  4、语法糖

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import time
##装饰器
def timer(func):
    def wrapper():
        start_time = time.time()
        func()
        end_time = time.time()
        print("函数func的运行时间为:%s" %(end_time-start_time))
    return wrapper
#原函数
@timer #函数优化:语法糖@timer= test = timer(test),在原函数前面加上@timer
def test():
    time.sleep(3)
    print("test函数运行完毕")
test()

 函数再次优化,获取test函数的返回值

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import time
##装饰器
def timer(func):
    def wrapper():
        start_time = time.time()
        ###获取test函数的返回值
        res = func()
        end_time = time.time()
        print("函数func的运行时间为:%s" %(end_time-start_time))
        return res
    return wrapper
#原函数
@timer #函数优化:语法糖@timer= test = timer(test),在原函数前面加上@timer
def test():
    time.sleep(3)
    print("test函数运行完毕")
    return "这是来自test函数的运行结果"
res = test() ##此时test()就是在运行wrapper函数
print(res)

 (1)、装饰器修改多个带参的函数

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import time
##装饰器
def timer(func):
    def wrapper(*args,**kwargs):
        start_time = time.time()
        ###获取test函数的返回值
        res = func(*args,**kwargs)
        end_time = time.time()
        print("函数%s的运行时间为:%s" %(func,end_time-start_time))
        return res
    return wrapper
###当装饰器修饰带参的函数且为多个函数时,由于每个被修饰的函数的
###形参个数不同,为了使装饰器接收任意长度的参数,故将装饰器函数的
###参数写为可以接收任意长度,任意类型的形参
#原函数
@timer #函数优化:语法糖@timer= test = timer(test),在原函数前面加上@timer
####优化原函数为带参的参数
def test(name,age,gender):
    time.sleep(3)
    print("test函数运行完毕")
    return "这是来自test函数的运行结果"
@timer
def test1(name,age,gender,addr):
    time.sleep(3)
    print("test1函数运行完毕")
    return "这是来自test1函数的运行结果"
res = test("尼古拉斯赵四",19,"male") ##此时test()就是在运行wrapper函数
print(res)
res1 = test1("尼古拉斯赵四",19,"male","重庆市")
print(res1)

 (2)、解压序列:这种方法非常有用,可以快速地取到最大值和最小值

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
#解压序列
l = (1,2,3)
a,b,c =l
print(a,b,c) #1 2 3
#使用解压序列进行取值:去掉最高分和去掉最低分
l = [10,2,4,5,6,7,8,9,9,4]
#升序排列
l.sort()
#这种解压序列可以很快就取到第一位和最后一位;
#*_表示中间的所有值
a,*_,b = l
print("最低分为:%s,最高分为:%s" %(a,b)) #print("最低分为:%s,最高分为:%s" %(a,b))
print(*_)  #4 4 5 6 7 8 9 9

 (3)、补充:两变量值互相交换

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
a = 1
b = 2
x = a
a = b
b = x
print(a,b)
f1 = 1
f2 = 2
f1,f2 = f2,f1
print(f1,f2)

 (4)、为函数加上验证功能:

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import time
def timer(func):
    def identer(*args,**kwargs):

        while True:
            name = input("请输入用户名:")
            password = input("请输入密码:")
            if name == "zhangsan@163.com" and password == "zhangsan":
               print("欢迎登陆:%s,登陆时间为:%s" %(name,time.time()))
               start_time = time.time()
               res = func(*args, **kwargs)
               end_time = time.time()
               print("函数%s运行时间为:%s" % (func, end_time - start_time))
               return res
               break
            else:
                print("用户名或者密码输入错误,请重新输入!!!!!")




    return identer
@timer
#原函数加上验证功能
def index():
    pass
@timer
def home():
    pass
@timer
def shopping_cat():
    pass
@timer
def order():
    pass
res = home()
print(res)

  

原文地址:https://www.cnblogs.com/tengjiang/p/11604759.html