首页 > 编程语言 >python的装饰器

python的装饰器

时间:2023-10-07 16:34:15浏览次数:34  
标签:comment 函数 python print inner fn 装饰 def

python的装饰器

1、装饰器的定义

已有的函数添加额外功能的函数,它本质上就是一个闭包函数

装饰器的功能特点:

  1. 不修改已有函数的功能特点
  2. 不修改已有函数的调用方式
  3. 给已有函数添加额外的功能

需求:给comment函数添加一个额外功能(需要先登陆,再评论)

要求:不能改变现有comment函数,不能修改comment函数的调用方式,还要添加一个额外功能

答:可以使用装饰器实现,装饰器的本质是一个闭包函数 =》① 有嵌套 ② 有引用 ③ 有返回

# 装饰器都有一个参数fn,代表要装饰函数的名称
def loggin(fn):
    def inner():
        # 在引用fn函数之前,添加额外功能
        print('请先登陆!')

        # 引用局部变量
        fn()

    return inner


@loggin
def comment():
    print('发表评论:')


comment()

2、案例之给程序额外添加一个计算时间的功能

import time


def get_time(fn):
    # 定义一个内部函数
    def inner():
        star = time.time()
        # 有引用
        fn()
        end = time.time()
        print(f'此程序执行了{(end - star):.02f}秒!')

    # 返回内部函数的地址
    return inner


@get_time  # 在使用装饰器的时候自动将函数地址传给装饰器
def demo():
    list1 = []
    for i in range(10000000):
        list1.append(i)


demo()

3、装饰器的执行原理

image-20231003170154399

def logging(fn):
    # fn = comment
    def inner():
        # 在引用fn函数之前,添加额外功能
        print('请先登陆!')

        # 引用局部变量
        fn()

    return inner


@logging  # 这里相当于将comment的地址作为参数传给了logging
def comment():
    print('发表评论:')


comment()   # 并不是执行comment函数,而是执行logging函数的返回结果,inner函数

以下代码效果等同

def logging(fn):
    def inner():
        print('请先登陆!')
        fn()

    return inner


def comment():
    print('发表评论')

# 等同于@logging 的效果
comment = logging(comment)  # 为了满足装饰器的不能修改调用的方式的需求,这里使用同名变量
comment()  # 这里调用的是inner函数,而不是comment函数,全局变量的优先级更大

4、装饰器修饰带有参数的函数

def message(fn):
    # fn = sum_num
    def inner(a, b):  # 要修饰的函数带有参数
        print('-----日志信息:正在努力计算中....-----')
        fn(a, b)  # fn(a, b) 等同于 sum_num(num1, num2)

    return inner


@message
def sum_num(num1, num2):
    print(num1 + num2)


# 这里实际调用的不是sum_num函数,而是inner函数,所以在inner函数中需要添加位置参数
sum_num(10, 20)

5、装饰器修饰带有不定长参数的函数

def message(fn):
    def inner(*args, **kwargs):
        print('----日志信息:正在努力计算....----')
        fn(*args, **kwargs)

    return inner


def sum_num(*args, **kwargs):
    sum1 = 0
    for i in args:
        sum1 += i
    for value in kwargs.values():
        sum1 += value
    print(sum1)


sum_num(10, 20, a=30, b=20)

6、装饰修饰带有返回值的函数

def message(fn):
    def inner(num1, num2):  # 在inner函数就没有返回,输出print()只能得到None
        print('----输入日志:正在努力计算....----')
        # fn(num1, num2)  # =》 func(10,20) => 30 并不会得到返回值
        return fn(num1, num2)

    return inner


@message
def func(num1, num2):
    result = num1 + num2
    return result


print(func(10, 20))  # func(10,20) => inner(10,20) =>需要在inner函数输入返回值

7、(重点)通用装饰器的编写

① 有嵌套 ② 有引用 ③ 有不定长参数 ④ 有return返回值 ⑤ 返回内部函数的地址

def message(fn):
    def inner(*args, **kwargs): 
        print('----日志信息:正在努力计算....----')
        return fn(*args, **kwargs)  

    return inner


@message
def sum_num(num1, num2):
    result = num1 + num2
    return result


print(sum_num(10, 20))

8、带有参数的装饰器

定义:在使用装饰器 装饰函数的时候可以传入指定参数,让装饰器内部使用。

语法:@装饰器(参数....)

实现方法:由于装饰器函数只能有一个参数,就是被装饰函数引用,所以实现方法就是“将装饰器放进一个函数内部,外部函数接收参数,给装饰器使用

def decoration(flag): # 再套入一层函数
    def message(fn):
        def inner(*args, **kwargs):
            if flag == '+':
                print('----输出日志:正在进行加法运算----')
            elif flag == '-':
                print('----输出日志:正在进行减法运算----')
            return fn(*args, **kwargs)

        return inner

    return message  # 都需要返回内层函数


@decoration('+')
def sum_num(num1, num2):
    return num1 + num2


@decoration('-')
def sub_num(num1, num2):
    return num1 - num2


print(sum_num(10, 20))
print(sum_num(20, 10))

9、类装饰器

类装饰器的编写规则:

① 必须要有一个__init__初始化方法,用于接收要装饰函数的函数

② 必须要把这个类转化为可以调用的函数 ( __call__())

class Check(object):
    # fn就是要装饰函数的名称,当Check装饰器类被调用时,系统自动将comment函数传递给comment变量
    def __init__(self, fn):
        self.__fn = fn

    def __call__(self, *args, **kwargs):
        # 编写装饰器代码
        print('登陆功能')
        # 调用comment函数本身
        self.__fn(*args, **kwargs)


# 编写一个函数实现评论功能,底层comment = Check(comment)
@Check
def comment():
    print('评论功能')

comment()

标签:comment,函数,python,print,inner,fn,装饰,def
From: https://www.cnblogs.com/luoluoange/p/17746619.html

相关文章

  • python日志logger
    写代码过程中,为了方便问题定位,经常需要打印信息,但是太多的print()不好,所以可以用到loggerLogger通常分为两类:一类是StreamHandler,将日志信息输出到控制台;另一类是FileHandler,将日志信息输出到文件。Python标准库中的logging模块提供了强大的Logger功能。importloggingcla......
  • python+playwright 元素操作
    Playwright可以与HTML输入元素交互,例如文本输入、复选框、单选按钮、选择选项、鼠标单击、键入字符、键和快捷方式以及上传文件和焦点元素。fill()输入文字使用 locator.fill() 是填写表单字段的最简单方法。它聚焦元素并input使用输入的文本触发事件。它适用于<input>,<t......
  • Python笔记目录
    Python笔记目录本视频学习自b站python视频,原地址在此笔记在原版笔记的基础上根据自己的理解做了调整,与原版的顺序和内容有有些区别笔记仅供学习使用,侵删第一章Python的安装、卸载第二章PyCharm的下载、安装、使用第三章Python的编写和运行第四章Python的基础语法......
  • python+playwright 元素定位
    元素定位官方文档:https://playwright.dev/python/docs/locators#lists元素操作官方文档:https://playwright.dev/python/docs/next/api/class-locator#methods1、xpath定位打开百度网页,点击导航-新闻#xpah//*[@id="s-top-left"]/a[1]page.click('xpath=//*[@id="s-top-......
  • python 3.12.0 perf 试用
    python3.12.0的发布,官方支持了基于perf的调用链分析,基于容器搞了一个简单的环境测试下环境准备包含了包含perf的python基础镜像,以及一个使用flask的web服务,使用flamescope的可视化页面分析docker-compose文件version:'3'services:flamescope:......
  • AIGC革新,将文字或者LOGO融入AI视频基于PIKA-labs(Python3.10)
    很多平台都会禁止用户使用带有网址或者二维码的头像以及文章配图,这样可以有效的防止用户的一些“导流”行为。当然,头像、文章或者视频现在都是AI来审,毕竟现在人工的成本实在太高,但是如果我们把文字元素直接融入图像或者视频之中,如此一来,AI也会很难识别出一些“导流”的元素。本次......
  • Python简易HTTP文件服务器
    我超怕的-HTTPsimplefileserverusePython-https://www.cnblogs.com/iAmSoScArEd/p/17745959.htmlHowtouse安装依赖:pip3installflask保存到文本simple_file_server.py后运行:python3simple_file_server.py浏览器访问:http://ip:9999CodefromflaskimportFlask,......
  • python TCP Server
    pythonTCPServerhttps://blog.csdn.net/weixin_45707610/article/details/131511896 下面的代码,要先关闭防火墙,然后再启动fromsocketserverimportBaseRequestHandler,TCPServerclassEchoHandler(BaseRequestHandler):defhandle(self):print('Got......
  • python+playwright 简单使用
    启动浏览器并打开百度页面安装后,您可以在Python脚本中使用Playwright,并启动3种浏览器中的任何一种(chromium,firefox和webkit)。playwright执行默认运行的浏览器是chromium1、同步方式启动浏览器2、异步方式启动浏览器 ......
  • python+playwright 环境准备
    前言2020年微软开源一个UI自动化测试工具Playwright,与selenium一样,入门简单,支持多语言,所以playwright开始被更多人注意到了,它甚至比selenium更好用更强大。playwright的优势跨浏览器和平台跨浏览器。Playwright支持所有现代渲染引擎,包括Chromium、WebKit和Firefox。......