avatar

AngYi

Aim for the stars, and beyond.

  • 首页
  • 分类
  • 标签
  • 归档
  • 相册
  • 关于我
Home Python 装饰器
文章

Python 装饰器

Posted 2021-12-13 Updated 2023-10- 17
By AngYi
8~11 min read

python装饰器

装饰器用一句话解释,就是python闭包函数的一种语法糖,用来对函数进行辅助。

闭包本身是一个函数,其传入参数和返回值都是函数,有点切面编程的工厂设计模式的意思在里边感觉。

现在我们由浅入深来实现一个python装饰器的使用场景,并引出装饰器。

实现一个功能,记录查找1到100中奇数这个函数的执行时间。

1. 原始方法

import time

def print_odds():
    start_time = time.perf_counter()
    
    for i in range(100):
        if i % 2 != 0:
            print(i)
    end_time = time.perf_counter()
    
    print(f'运行总时间为{end_time - start_time}')


if __name__ == '__main__':
    print_odds()

缺点:函数主要逻辑不突出,辅助功能在函数内部占用地方,不利于维护。

2. 拆分主要函数和辅助函数

import time


def count_time(func):
    start_time = time.perf_counter()
    func()
    end_time = time.perf_counter()
    print(f'运行总时间为{end_time - start_time}')


def print_odds():
    for i in range(100):
        if i % 2 != 0:
            print(i)


if __name__ == '__main__':
    count_time(print_odds)

这样写的话主函数功能逻辑和辅助函数就能够解耦合了,但是对外调用的接口是辅助函数,不利用使用者使用。

3. 函数闭包

import time

# 闭包函数,本质是一个函数,传入和返回都是函数
def count_time(func):
    def improve_func():
        start_time = time.perf_counter()
        func()
        end_time = time.perf_counter()
        print(f'运行总时间为{end_time - start_time}')

    return improve_func


def print_odds():
    for i in range(100):
        if i % 2 != 0:
            print(i)


if __name__ == '__main__':
    print_odds = count_time(print_odds)
    print_odds()

这样做的话是不是就解决了上面第2点说的缺点,这里用到的就是闭包函数,这里要注意的点就是函数作为参数和返回的时候都是不加括号的。

但是这样写还是不够简洁,而且需要提前显式调用闭包函数对函数进行增强。

4. 装饰器

import time


def count_time(func):
    def improve_func():
        start_time = time.perf_counter()
        func()
        end_time = time.perf_counter()
        print(f'运行总时间为{end_time - start_time}')

    return improve_func


@count_time
def print_odds():
    for i in range(100):
        if i % 2 != 0:
            print(i)


if __name__ == '__main__':
    print_odds()

装饰器增强只增强一次,且在第一次调用时增强。

通用的装饰器

def general_wrapper(func):
  
  def wrapper(*args,**kwargs):
    ret  =  func(*args,**kwargs)
    return ret 
  
  return wrapper

5. 有参数的装饰器

import time


def count_time(param):
    print(param)
    def improve_func(func):
        def wrapper(*args,**kwargs):
            start_time = time.perf_counter()
            func(*args,**kwargs)
            end_time = time.perf_counter()
            print(f'运行总时间为{end_time - start_time}')
        return wrapper
    return improve_func


@count_time(123)
def print_odds(lim = 100):
    for i in range(lim):
        if i % 2 != 0:
            print(i)


if __name__ == '__main__':
    print_odds()
编程语言
python
License:  CC BY 4.0
Share

Further Reading

Oct 15, 2022

Python算发开发项目模版

1. 前言这篇文章主要介绍如何编写有组织的、模块化的和可扩展的python代码。一个机器学习或者深度学习的工程项目,应该像软件开发一样,被视为一个整体。因此,这个项目应该具备这些东西:OOP,TypeChecking,Doc。模块之间遵循设计模式最根本的原则:低耦合高内聚。

Apr 18, 2022

JavaScript基础

JavaScript1. 简介JavaScript(简称“JS”) 是一种具有函数优先的轻量级,解释型或即时编译型的高级编程语言。虽然它是作为开发Web页面的脚本语言而出名的,但是它也被用到了很多非浏览器环境中,JavaScript 基于原型编程、多范式的动态脚本语言,并且支持面向对象、命令式和声明

Apr 4, 2022

python 协程、async & 异步

OLDER

【Flask开发】 2. 路由与蓝图

NEWER

局域网无网络服务器联网解决方案

Recently Updated

  • DeepSeek 创始人梁文峰采访:创新、人才与中国 AI 发展
  • 福州-厦门之行
  • 我有自己的摄影网站啦
  • 借助Ollama一键本地部署CodeGeex,让AI帮你打工
  • Dash 进阶技巧

Trending Tags

ssh linux matlab 感悟 读书 blog git python flask ML

Contents

©2025 AngYi. Some rights reserved.

Using the Halo theme Chirpy