Python3——装饰器及应用(这个属于详细的)

转自:https://blog.csdn.net/loveliuzz/article/details/77853346    说明:本文代码是原作者编写,有一些不适应我的环境的代码我进行了删除修改等操作,特此说明!

解释的很全面!

1、装饰器:

(1)本质:装饰器的本质是函数,其基本语法都是用关键字def去定义的。

(2)功能:装饰其他函数,即:为其他函数添加附加功能。

(3)原则:不能修改被装饰的函数的源代码,不能修改被装饰的函数的调用方式。即:装饰器对待被修饰的函数是完全透明的。

(4)简单应用:统计函数运行时间的装饰器

import time  

#统计函数运行时间的砖装饰器
def timmer(func):
    def warpper(*args,**kwargs):
        strat_time = time.time()
        func()
        stop_time = time.time()
        print("the func run time is %s" %(stop_time-strat_time))
    return warpper  

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

test1()  

#运行结果:
#in the test1
#the func run time is 3.000171661376953  

(5)实现装饰器知识储备:

a、函数即“变量”

b、高阶函数

c、函数嵌套

d、高阶函数+嵌套函数==》装饰器

2、装饰器知识储备——函数即“变量”

定义一个函数,相当于把函数体赋值给这个函数名。

Python解释器如何回收变量:采用引用计数。当引用有没有了时(门牌号不存在),变量就被回收了。

函数的定义也有内存回收机制,与变量回收机制一样。匿名函数没有函数名,就会被回收。

变量的使用:先定义再调用,只要在调用之前已经存在(定义)即可;函数即“变量”,函数的使用是一样的。

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

下面的两段代码运行效果一样:

def bar():
    print("in the bar")
def foo():
    print("in the foo")
    bar()
foo()  

#python为解释执行,函数foo在调用前已经声明了bar和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  

注意:python为解释执行,函数foo在调用前已经声明了bar和foo,所以bar和foo无顺序之分

3、装饰器知识储备——高阶函数

满足下列其中一种即可称之为高阶函数:

a、把一个函数名当做实参传递给另一个函数(在不修改被装饰函数的情况下为其添加附加功能)

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

(1)高阶函数示例:

def bar():
    print("in the bar")  

def test1(func):
    print(func)    #打印门牌号,即内存地址
    func()  

test1(bar)      #门牌号func=bar  

#运行结果:
#<function bar at 0x00BCDFA8>
#in the bar  

(2)高阶函数的妙处——把一个函数名当做实参传递给另一个函数(在不修改被装饰函数的情况下为其添加附加功能)

import  time  

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

#test2在不修改被修饰函数bar的代码时添加了附加的及时功能
def test2(func):
    start_time = time.time()
    func()     #run bar
    stop_time = time.time()
    print("the func run time is %s " %(stop_time-start_time))  

#调用方式发生改变,不能像原来的方法去调用被修饰的函数(所以不能实现装饰器的功能)
test2(bar)
#bar()  

#运行结果:
#in the bar
#the func run time is 3.000171661376953   

(3)高阶函数的妙处——返回值中包含函数名(不修改函数的调用方式)

import  time
def bar():
     time.sleep(3)
     print("in the bar")  

def test3(func):
    print(func)
    return func  

li = test3(bar)
li()   #run li  相当于运行bar()  

#运行结果:
#<function bar at 0x00BADFA8>
#in the bar

4、装饰器知识储备——嵌套函数

#函数嵌套
def foo():
    print("in the foo")
    def bar():   #bar函数具有局部变量的特性,不能在外部调用,只能在内部调用
        print("in the bar")
    bar()  

foo()  

#运行结果:
#in the foo
#in the bar  

1、装饰器应用——模拟网站登录页面,访问需要认证登录页面

user,passwd = "liu","liu123"
def auth(func):
    def wrapper(*args,**kwargs):
        username = input("Username:").strip()
        password = input("Password:").strip()  

        if username == user and password == passwd:
            print("User has passed authentication!")
            res = func(*args,**kwargs)
            print("-----after authentication---")
            return res  

        else:
            exit("\033[31;1mInvalid username or password!\033[0m")
    return wrapper  

def index():
    print("welcome to index page!")  

@auth
def home():
    print("welcome to index home!")
    return "from home"  

@auth
def bbs():
    print("welcome to index bbs!")  

#函数调用
index()
print(home())
bbs()  

#运行结果:
#welcome to index page!
#Username:liu
#Password:liu123
#User has passed authentication!
#welcome to index home!
#-----after authentication---
#from home
#Username:liu
#Password:liu123
#User has passed authentication!
#welcome to index bbs!
#-----after authentication---  

2、装饰器带参数

user,passwd = "liu","liu123"
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 username == user and password == passwd:
                    print("\033[32;1mUser has passed authentication!\033[0m")
                    #被装饰的函数中有返回值,装饰器中传入的参数函数要有返回值
                    res = func(*args, **kwargs)    #from home
                    print("-----after authentication---")
                    return res  

                else:
                    exit("\033[31;1mInvalid username or password!\033[0m")
            elif auth_type == "ldap":
                print("ldap....")  

        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")       #利用远程的ldap登录
def bbs():
    print("welcome to bbs page!")  

#函数调用
index()
print(home())      #wrapper()
bbs() 

原文地址:https://www.cnblogs.com/loved/p/8678846.html

时间: 2024-11-10 06:15:38

Python3——装饰器及应用(这个属于详细的)的相关文章

python3 装饰器

看廖雪峰官网的python3装饰器有感 装饰器即将一个函数作为变量在新的函数中调用此函数. 作业: 能否写出一个@log的decorator,使它既支持: @logdef f():     pass 又支持: @log('execute')def f():     pass      例1: import functools import time def log(*args,**kwargs):     # *args 是个元组     if args and isinstance(args,

Python3装饰器

装饰器:本质是函数(装饰其他函数-->为其他函数添加功能) 原则:1.不能被修改装饰的源代码 2.不能修改被装饰的函数的调用方式知识储备:1.函数即"变量"2.高阶函数3.嵌套函数高阶函数+嵌套函数 = 装饰器 高阶函数:a.把一个函数名当做实参传给另一个函数 b.返回值中包含函数名嵌套函数: 仅用高阶函数实现的装饰器 高阶函数+嵌套函数:实现装饰器. 装饰器函数定义时,通过将需要装饰的函数(装饰器的形参)放在嵌套函数里面,嵌套在内层的函数只进行函数定义,不进行函数的调用(内含的

python3装饰器的简单解释

#闭包,也叫词法闭包:如下所示函数A主要是为了函数B提供运行环境的#闭包只是在表现和形式上像函数,其实闭包并不是函数#由函数在嵌套环境中,内层函数里,对外层函数作用域的变量进行了引用,那么在外层函数返回后,内层函数依然可是使用外层函数的变量,这样的变量就构成了可以使用时的环境#所以闭包对于隐藏状态,以及在函数和作用域中进行切换,一个函数可以发挥很多种功能# #闭包:如下所示我们只需要不断的变化f调用变化就可以是函数B跟着变化了 def A(num1,num2):     def B(x,y):

python3 装饰器修复技术@wraps到底是什么?

Python 装饰器中的@wraps的作用:    装饰器的作用:    在不改变原有功能代码的基础上,添加额外的功能,如用户验证等    @wraps(view_func)的作用:     不改变使用装饰器原有函数的结构(如__name__, __doc__)    不使用wraps可能出现的ERROR:   view_func...endpoint...map... 如果没使用@wraps,当A调用了装饰器B的话,即使A.name,返回的会是装饰器B的函数名称,而不是A的函数名称如果使用了@

Python装饰器详解,详细介绍它的应用场景

装饰器的应用场景 附加功能 数据的清理或添加: 函数参数类型验证 @require_ints 类似请求前拦截 数据格式转换 将函数返回字典改为 JSON/YAML 类似响应后篡改 为函数提供额外的数据 mock.patch 函数注册 在任务中心注册一个任务 注册一个带信号处理器的函数 不同应用场景下装饰器实现 函数注册表 简单注册表 funcs = [] def register(func): funcs.append(func) return func @register def a(): r

Python基础篇【第九篇】:剖析装饰器

装饰器:装饰器:装饰器的语法以@开头,然后是装饰器函数的名字和可选的参数,紧跟着装饰器声明的是被修饰的函数和装饰函数的可选参数.剖析装饰器: #!/usr/bin/env python3 ''' 装饰器:装饰器的语法以@开头,然后是装饰器函数的名字和可选的参数,紧跟着装饰器声明的是被修饰的函数和装饰函数的可选参数. 表现形式: def outer(): def inner(): print("xxx") return test return inner @outer def f1():

python3.5.2之装饰器(1)

一.本次实验环境: 在腾讯云虚拟主机centos7上配置pyenv多版本python管理器,并安装交互式web编辑器jupyter,python版本为3.5.2.  二.装饰器: 装饰器的本质是一个函数,接收一个函数作为参数,并且返回一个函数 带参数的装饰器是一个函数,返回一个装饰器 带参数的装饰器最多允许一层,timeit()()(不允许) 在python中,一个函数可以作为参数传递给另外一个函数,还可返回一个函数(不了解此请看高阶函数)因此,我们可以把一个函数传递给另一个函数后,在这个被传递

Python3.5:装饰器的使用

在Python里面函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数,简单来说函数也是变量也可以作文函数的参数 >>> def funA(): ... print('i an funA') ... time.sleep(1) >>> f = now >>> f() i am funA 函数对象有一个__name__属性,可以拿到函数的名字: >>> funA.__name__ 'funA' >>&

python3练习-装饰器

在廖雪峰的官方网站学习装饰器章节时,初步理解类似与面向切面编程.记录一下自己的课后习题解法. 问题: 请编写一个decorator,能在函数调用的前后打印出'begin call'和'end call'的日志.写出一个@log的decorator,使它既支持: @log def f(): pass 又支持: @log('execute') def f(): pass 示例代码(个人练习,如有问题欢迎斧正): # ! usr/bin/env python3 # -*- coding:utf-8 -