#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""装饰器"""
###### 第一波 ######

def foo():
    print('foo')

print('函数对象,表示foo这个函数', foo)
foo()  # 调用foo函数
###### 第二波 ######

def foo():
    print('foo')

def foo(x): return x + 1

print('foo函数被重定义了:', foo(1))
######## 基础平台部门提供的功能如下  ##########

def f1():
    print('f1')

def f2():
    print('f2')

def f3():
    print('f3')

def f4():
    print('f4')

########  业务部门A 调用基础平台部门提供的功能  ##########
f1()
f2()
f3()
f4()
########  业务部门B 调用基础平台部门提供的功能  ##########
f1()
f2()
f3()
f4()
# 问题:之前基础平台部门的开发人员在写代码的时候,没有考虑验证相关的问题,基础平台提供的功能可以被任何人使用。
# 现在需要对基础平台的所有功能进行重构,加入验证机制。即调用基础平台的功能时,先验证,再调用
# 解决方法:只对基础平台的代码进行重构,其他业务部门无需做任何修改
######## 基础平台部门提供的功能如下  ##########

def check_login():
     # 验证1
    # 验证2
    # 验证3
    pass

def f1():
    check_login()
    print('f1')

def f2():
    check_login()
    print('f2')

def f3():
    check_login()
    print('f3')

def f4():
    check_login()
    print('f4')
# 缺点: 写代码要遵循开放封闭的原则:即对扩展开发开放,对已实现的功能模块封闭;
# 改进:使用装饰器@w1----仅仅对基础平台的代码进行修改,其他业务部门的无需做任何操作
######## 修改后的基础平台部门提供的功能如下  ##########

def w1(func):
    def inner():
        # 验证1
        # 验证2
        # 验证3
        return func
    return inner

@w1
def f1():
    print('f1')

@w1
def f2():
    print('f2')

@w1
def f3():
    print('f3')

@w1
def f4():
    print('f4')

# 原理解释
"""单独以f1为例解释"""

def w1(func):
    def inner():
        # 验证1
        # 验证2
        # 验证3
        return func
    return inner

@w1
def f1():
    print('f1')

# 解释@w1内部会执行以下操作:
"""
执行w1函数,并将@w1下面的函数作为w1函数的参数,即:@w1等价于w1(f1)。即:将原来的f1函数塞进另一个函数中
接着,内部会执行下面的语句:
def inner():
    # 验证
    return f1  此时的func等于f1
return inner 
最后,将执行完的w1函数返回值赋值给@w1下面的函数的函数名 
w1函数的返回值:
    def inner:
        # 验证
        return 原来的f1()  
然后,将此返回值再重新赋值给f1
新f1 = def inner():
            # 验证
            return 原来的f1()
"""
# 一个参数

def w1(func):
    def inner(arg):
        # 验证
        return func(arg)
    return inner

@w1
def f1(arg):
    print('f1')
# 两个参数

def w1(func):
    def inner(arg1, arg2):
        # 验证
        return func(arg1, arg2)
    return inner

@w1
def f1(arg1, arg2):
    print('f1')
# 三个参数

def w1(func):
    def inner(arg1, arg2, arg3):
        # 验证
        return func(arg1, arg2, arg3)
    return inner

@w1
def f1(arg1, arg2, arg3):
    print('f1')
#  装饰具有n个参数的函数的装饰器

def w1(func):
    def inner(*argc, **kwargs):
        # 验证
        return func(*argc, **kwargs)
    return inner

@w1
def f1(arg1, arg2, arg3):
    print('f1')
# 同一个函数可以被多个装饰器修饰

def w1(func):
    def inner(*argc, **kwargs):
        # 验证
        return func(*argc, **kwargs)
    return inner

def w2(func):
    def inner(*argc, **kwargs):
        # 验证
        return func(*argc, **kwargs)
    return inner

@w1
@w2
def f1(arg1, arg2, arg3):
    print('f1')
# 装饰器实战

def now():
    print('2018-07-13')

f = now
print('函数对象', type(f))
f()
print('函数对象的name属性', f.__name__)
# 下面增强now函数的功能-----在函数调用前后自动打印日志,但又不修改now()函数定义-----在代码运行期间动态增加功能的方式,称为装饰器

def log(func):  # log()是一个装饰器,返回一个函数;原来的now函数仍然存在,但调用now函数相当于执行了一个新函数,即在log函数中返回的inner函数
    def inner(*args, **kwargs):
        print('调用%s():' % func.__name__)
        return func(*args, **kwargs)
    return inner

# 无参数装饰器
@log  # 相当于log(now)
def now():
    print('2018-07-13')

# 调用now函数
now()
# 如果装饰器函数本身需要传入一个参数,则函数结构更加复杂

# 带参数装饰器
def log(text):
    def decorator(func):
        def inner(*args, **kwargs):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kwargs)
        return inner
    return decorator

# 等价于log('execute')(now)-----首先执行 log('execute'),返回的是decorator函数,再调用返回的函数.参数是now函数,返回值最终是inner函数
@log('execute')
def now():
    print('2018-07-13')

# 调用now()函数
now()
# 经过装饰器装饰后的函数对象的属性已经改变
print(now.__name__)
# 解决方法:functools.wraps
import functools

def log(func):  # log()是一个装饰器,返回一个函数inner;原来的now函数仍然存在,但调用now函数相当于执行了一个新函数,即在log函数中返回的inner函数
    @functools.wraps(func)  # 此语句就是解决了由于原函数name属性复制到inner函数属性的问题,出现在返回函数定义之前
    def inner(*args, **kwargs):
        print('调用%s():' % func.__name__)
        return func(*args, **kwargs)
    return inner

@log
def now():
    print('2018-07-13')

# 已解决: 经过装饰器装饰后的函数对象的属性已经改变
print(now.__name__)

def log(text):
    def decorator(func):
        @functools.wraps(func)
        def inner(*args, **kwargs):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kwargs)
        return inner
    return decorator

# 等价于log('execute')(now)-----首先执行 log('execute'),返回的是decorator函数,再调用返回的函数.参数是now函数,返回值最终是inner函数
@log('execute')
def now():
    print('2018-07-13')

now()
print(now.__name__)
# 练习
import time
import functools

def metric(func):
    functools.wraps(func)

def wraper(*args, **kwargs):
        start = time.time()  # 执行前计时
        func(*args, **kwargs)  # 执行函数
        end = time.time()  # 执行后计时
        print("%s executed in %s ms" % (func.__name__, 1000 * (end - start)))
        return func(*args, **kwargs)
    return wraper

@metric
def fast(x, y):
    time.sleep(0.0012)
    return x + y

@metric
def slow(x, y, z):
    time.sleep(0.1234)
    return x * y * z

f = fast(11, 22)
print(f)

s = slow(11, 22, 33)
print(s)
# 测试过程
if f != 33:
    print('测试失败!')
elif s != 7986:
    print('测试失败!')
# 练习2

def log1(arg):
    if not isinstance(arg, str):
        func = arg
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('begin call %s' % (func.__name__))
            r = func(*args, **kw)
            print('end call %s' % (func.__name__))
            return r
        return wrapper
    else:
        text = arg
        def decorator(func):
            @functools.wraps(func)
            def wrapper(*args, **kw):
                print('begin %s %s()' % (text, func.__name__))
                r = func(*args, **kw)
                print('end %s %s()' % (text, func.__name__))
                return r
            return wrapper
        return decorator

@log1
def now1():
    print('2018-07-13')
now1()
print('-----------------')
@log1('execute')
def now1():
    print('2018-07-13')
now1()

python3语法糖------装饰器相关推荐

  1. python3语法糖_python3语法糖

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 切片操作像列表这类可以支持**切片**操作的对象,则是我最初喜欢python的一 ...

  2. Python3中的装饰器

    一.装饰器 1.定义:从字面上理解,就是装饰对象的器件.可以在不修改原有代码的情况下,为被装饰的对象增加新的功能或者附加限制条件或者帮助输出.装饰器有很多种,有函数的装饰器,也有类的装饰器.装饰器在很 ...

  3. python装饰器函数-【python3】 函数 装饰器

    第一步 : 了解装饰器 装饰器模式,重点在于装饰,装饰的核心仍是被装饰的对象. 举一个栗子:我今天穿了一件短袖,但是突然一阵风,短袖没办法为我御寒,我想到的办法是将短袖变得更厚更长,但是改造之后,它就 ...

  4. python3 如何给装饰器传递参数

    [引子] 之前写过一篇文章用来讲解装饰器(https://www.cnblogs.com/JiangLe/p/9309330.html) .那篇文章的定位是入门级的 所以也就没有讲过多的高级主题,决定 ...

  5. ts可展开注释_TS语法之装饰器(注解)

    写在前面的话 本文只讲解 TypeScript 中的装饰器语法(下称注解), 只会告诉你如何编写一个自定义注解,且通过注解简单的修改逻辑,不涉及 反射 或 元编程 等其他更进一步的代码讲解,如果有兴趣 ...

  6. python3语法糖_python的语法糖

    # -*- coding: utf-8 -*- def deco(func): print("before myfunc() called.") func() print(&quo ...

  7. python3语法糖_Python笔记3:语法糖

    运算 数字运算 运算会根据结果自动判断结果是int还是float 用到除法的时候,结果自动输出为float 双斜杠//得到的结果是int 取模(余数)还是% >>> 2+2 4 &g ...

  8. SIGIA_4P python学习 列表 字典 集合 面对对象编程 闭包 装饰器 函数式编程 作用域 异常处理

    SIGIA_4P python学习 列表 字典 集合 面对对象编程 闭包 装饰器 函数式编程 作用域 异常处理 本文连接 简介 SIGIA_4P 网址 a. 课程OKR Objectives and ...

  9. python之函数三装饰器

    装饰器形成的过程 装饰器的作用:不想修改函数的调用方式,但是还想在原来的函数前后加功能 原则:开发封闭原则 开发:对扩展是开发的 封闭:对修改是封闭的 装饰器的固定模式 计算运行时间 1 import ...

最新文章

  1. Navicat链接数据库报错1130解决方案
  2. 计算机网络实验仿真系统设计,计算机网络实验课程仿真系统平台的研究与设计...
  3. UML 中各种图形重要性的排行
  4. 在MSF中怎么区分易混淆的工作项类型:Bug、风险和问题(我个人的理解)
  5. 一文带你了解数仓智能运维框架
  6. linux python指向python3_linux下切换python2和python3(转)
  7. TypeError: __str__ returned non-string (type NoneType)
  8. python中质数的表达方式_python求质数的3种方法
  9. BUAA软工第0次作业
  10. 【招聘】智联NLP算法工程师
  11. python查看系统信息_Python脚本获取操作系统版本信息
  12. python语言的赋值语句可以改变变量的类型吗_python 数据类型和变量
  13. X86 MOVSB MOVSW MOVSD MOVSQ 指令详解
  14. 设置导航标题颜色以及导航条背景色
  15. 将Linux下文件目录使用Nginx代理使浏览器可访问
  16. keras中的后端backend及其相关函数(K.prod,K.cast)
  17. j1900做网站服务器,j1900可以跟云服务器
  18. java程序设计——实验四
  19. 关于游戏中的数据分析
  20. 一种结合基于股债利差的A股估值百分位、有限价值策略定投和股债组合投资的创新型低回撤高收益稳健理财方法

热门文章

  1. HttpURLConnection IllegalStateException
  2. Linux SVN命令详解
  3. iOS 消息的传递机制
  4. python基础学习笔记(六)
  5. 如何彻底禁用VS 2008的智能感知功能
  6. 一起谈.NET技术,linq2sql:直接执行sql语句
  7. 子窗体更新父窗体控件内容
  8. 程序人生--从这里开始
  9. 活动目录(Active Directory)域故障解决实例
  10. MySQL优化篇:IN VS EXISTS