装饰器函数的构造

装饰器函数的构造

由于软件的设计遵循开发封闭原则(对于扩展开发,对于程序修改封闭)。所以对于软件的扩展是对软件二次开发的最好途径。这时候就需要使用到装饰器这个概念了。

装饰器就是为装饰的对象添加新的功能,并且是在不修改源码的情况下,还必须使得在外行看起来没有发生任何变化(调用方法、软件实现主要功能……)。

装饰器分为无参装饰器和有参装饰器,装饰器的实现都是通过“函数嵌套+闭包+函数对象”组合生成的。

装饰器模板

def outter(func):
	# 传进来的是被装饰的函数的对象
	def wrapper(*args,**kwargs):
		res = func(*args,**kwargs)
		return res
	return wrapper

@outter
def index(x,y):
	print(x,y)

无参装饰器的实现

import time

# 定义一个小函数
def index():
    time.sleeep(1.5)
    print("Welcome to index page!!!")
    return 100

index()            # 调用函数

如果需要在这个函数调用时候添加一个功能:就是实现输出调用函数需要使用的时间,虽然说这个功能实现很简单,并没有什么复杂的,但是如果只是使用下面的这种解法,那么就太老土了。
解法一:(老土、麻烦)

start = time.time()
index()            # 调用函数
print("用时:",time.time()-start)

这样子对于只是一个两个函数的时候,就能够简单实现,但是如果很多的函数调用都需要输出时间的时候就会很麻烦了,代码量也会变得很累赘了。

解法二:(调用方式改变了,不是很合要求)

def timer(fun):
    start = time.time()
    fun()            # 调用函数
    print("用时:",time.time()-start)
 
timer(index)         # 调用一个新的函数,实现所需要的功能

这个方法是对第一个方法的改进,减少了代码量,但是同时也带来了一个缺点,那就是改变了调用方式,这样子好像不太满足要求了。

解法三:(使用装饰器)

import time

def timer(func):
    def wrapper(): # 引用外部作用域的变量func
        start_time=time.time()
        res=func()
        stop_time=time.time()
        print('run time is %s' %(stop_time-start_time))
        return res
    return wrapper
  
 # 定义一个小函数
@ timer                    # 添加装饰器对象
def index():
    time.sleeep(1.5)
    print("Welcome to index page!!!")
    return 100

# 这时候的调用方式
index()               # 调用函数,但是这时候调用的函数就不再是原先的index函数了,而是加了装饰器的index函数

使用装饰器之后,调用方式没有发生任何的改变,同时也实现了附加的功能;同时如果还有其他的函数想要实现这个种附加的功能也这需要添加一个装饰器就可以了。

有参装饰器的实现

由于语法糖 @ 的限制,outter函数只能有一个参数,并且这才是只用来接受被装饰对象的内存地址

# 定义一个验证功能的装饰器
def auth(driver):      # 最高层传递参数(第三层)
    def deco(func):
        def wrapper(*args,**kwargs):
            name = input("input user>>").strip()
            pwd = input("input pwd>>").strip()
            if driver == 'file':
                print("基于文件验证")
                # 编写基于文件的认证,认证通过则执行res=func(*args,**kwargs),并返回res
                
                # 打开文件,传文件中读取用户信息进行匹配
                if name == "xiaoming" and pwd == "123456":
                    print("基于文件验证成功")
                else:
                    print("基于文件验证失败")

            elif driver == 'mysql':
                # 编写基于mysql认证,认证通过则执行res=func(*args,**kwargs),并返回res
                print("基于数据库验证")
                if name == "xiaoming" and pwd == "123456":
                    print("基于数据库验证成功")
                else:
                    print("基于数据库验证失败")

            else:
                print("传入验证参数有误")
        return wrapper
    return deco


# auth(driver="file") ----- 运行之后返回一个deco函数的内存地址;(添加这一层闭包的主要功能就是为了传递参数)
# @deco 这个就是一般的装饰器语法糖(一个两层的闭包函数)
@auth(driver="file")
def index(x,y):
    print("index{}{}".format(x,y))


@auth(driver="mysql")
def home(x,y):
    print("index{}{}".format(x,y))


index(2,6)

home(5,9)

综合以上操作就实现了有参装饰器的传递,但是还存在一个问题,就是虽然有参装饰器是实现了,并且调用方式都没发生任何的变化,但是还有一个问题,那就是函数的属性以及一些其他的附加内容,并没有进行修改,这时候其实需要把他们全部进行修改才是一个完美的装饰器。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/115127.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 数字游戏13524_数字表达

    数字游戏13524_数字表达由于科协里最近真的很流行数字游戏。某人又命名了一种取模数,这种数字必须满足各位数字之和 mod N 为 0。现在大家又要玩游戏了,指定一个整数闭区间 [a.b],问这个区间内有多少个取模数。输入格式输入包含多组测试数据,每组数据占一行。每组数据包含三个整数 a,b,N。输出格式对于每个测试数据输出一行结果,表示区间内各位数字和 mod N 为 0 的数的个数。数据范围1≤a,b≤231−1,1≤N<100输入样例:1 19 9输出样例:2#include<bits

  • VS Code 迎来新对手?JetBrains发布新一代轻量编辑器——Fleet

    VS Code 迎来新对手?JetBrains发布新一代轻量编辑器——Fleet11月29日,Jetbrains官网发布一个重大消息,即公布了一个轻量级编辑器——Fleet。????https://www.jetbrains.com/zh-cn/fleet/Fleet作为一个功能齐全的编辑器启动,具有语法高亮显示、简单的代码补全,以及用户对一个编辑器期待的所有功能,比如智能补全、重构、导航、调试等功能。话不多说,下面让我们了解一下Fleet新功能吧。Fleet适用于多种场景和多类编程语言JetBrains官方认为开发者通常在不同的项目中会使用到不同的技术,有时在单个项目

  • adnroid仿miui的dialog

    adnroid仿miui的dialog

    2021年12月13日
  • 网管最看重的五种远程控制软件

    网管最看重的五种远程控制软件

  • 雅典娜暴利烹饪系列(下)「建议收藏」

    雅典娜暴利烹饪系列(下)「建议收藏」”呀–呀–呀–“爬到冰箱上的纱织吓的花容失色,”快点把那些土鳖拿开啦—-“端着一盆螃蟹的迪马斯头上好几个”加号”:”你叫个什么劲呀!!!不是你要学煮螃蟹,叫我下河给你捞的吗?!!这是螃蟹!!!螃蟹!!!!”纱织眼睛里无辜的泪水在打转:”骗人!螃蟹明明是红色的~~~””那是煮熟的好不好!!!”迪马斯已经在昏倒的边缘,”快拿去!!!””不要呀~~~~好可怕呀~~~~~”玉手一挥,螃蟹

  • 【剑指offer】第一个仅仅出现一次的字符

    【剑指offer】第一个仅仅出现一次的字符

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号