python通用运行时间装饰器

最近在用 Python3 写一个程序,功能已经实现了,但是运行速度太慢了,慢到令人发指,为了让这个程序的存在具有意义,我需要把这些功能函数耗费的时间大概了解,找出那些运行时间比较长的,之后有针对性地解决

所以,获取程序中各函数运行时间成了当务之急,这里涉及两个小困难:

  • 函数众多,在每个函数中都加上计算时间的代码会很繁琐,最后还得删除

    这个解决起来不难,用装饰器就可以解决,不需要修改代码

  • 函数绝大多数都定义在类中,这样普通的运行时间装饰器就会产生不兼容的情况

    所以就有了下面这个通用装饰器

import datetime
import wrapt
import inspect


# 通用时间装饰器
@wrapt.decorator
def universal(wrapped, instance, args, kwargs):
    if instance is None:
        if inspect.isclass(wrapped):
            # 装饰一个类
            # Decorator was applied to a class.
            return wrapped(*args, **kwargs)
        else:
           # 装饰一个普通函数或者静态方法
            # Decorator was applied to a function or staticmethod.
            ret = consume_time(wrapped=wrapped, args=args, kwargs=kwargs)
            return ret
    else:
        if inspect.isclass(instance):
            # 装饰类方法
            # Decorator was applied to a classmethod.
            ret = consume_time(wrapped=wrapped, args=args, kwargs=kwargs)
            return ret
        else:
           # 装饰实例方法
            ret = consume_time(wrapped=wrapped, args=args, kwargs=kwargs)
            return ret
           
def consume_time(wrapped, args, kwargs):
    local_time = datetime.datetime.now()
    ret = wrapped(*args, **kwargs)
    times = (datetime.datetime.now() - local_time).seconds
    funcname = wrapped.__name__
    print('运行 {} 函数消耗的时间为 {} 分 {} 秒'.format(
        funcname, times // 60, times % 60))
    # print('Run {} time is {} minutes {} seconds'.format(
    #     funcname, times // 60, times % 60))
    return ret

既然说是通用装饰器,怎么个通用法呢?它可以作用于以下内容

  • 普通函数

  • 类静态方法

  • 类方法

  • 实例方法

接下来我们测试一下

【未加装饰器的程序】

import time


class People:
    # 定义基本属性
    name = ""
    age = 0

    # 初始化函数
    def __init__(self, name, age):
        self.name = name
        self.age = age 
    
    # 静态方法
    @staticmethod
    def work():
        time.sleep(3)
        print("I could work")

    # 类方法
    @classmethod
    def speak(cls, words):
        time.sleep(1)
        print(words)

    # 实例方法
    def eat(self, food):
        time.sleep(5)
        print(f"I am eating {food}")
    
# 普通函数
def read(bookname):
    time.sleep(1)
    print(f"I am reading {bookname}")


# 调用普通函数
read("《Linux 二进制分析》")

# 调用静态方法
People.work()

# 调用类方法
People.speak("hello world")

## 调用实例方法
# 实例化一个对象
xiaoming = People(name="xiaoming", age=18)
xiaoming.eat("a sandwich")

运行后结果

图片

现在我们加上时间装饰器,来看看这些函数都消耗了多少时间

【已经加上装饰器的程序】

为了演示装饰不同内容,我们给装饰器每个分支都加上 print

import datetime
import time
import wrapt
import inspect


@wrapt.decorator
def universal(wrapped, instance, args, kwargs):
    funcname = wrapped.__name__
    if instance is None:
        if inspect.isclass(wrapped):
            print("-" * 50)
            print("正在装饰一个类")
            return wrapped(*args, **kwargs)
        else:
            print("-" * 50)
            print(f"正在装饰一个普通函数或者静态方法: {funcname}")
            ret = consume_time(wrapped=wrapped, args=args, kwargs=kwargs)
            return ret
    else:
        if inspect.isclass(instance):
            print("-" * 50)
            print(f"正在装饰类方法: {funcname}")
            ret = consume_time(wrapped=wrapped, args=args, kwargs=kwargs)
            return ret
        else:
            print("-" * 50)
            print(f"正在装饰实例方法: {funcname}")
            ret = consume_time(wrapped=wrapped, args=args, kwargs=kwargs)
            print("-" * 50)
            return ret

def consume_time(wrapped, args, kwargs):
    local_time = datetime.datetime.now()
    ret = wrapped(*args, **kwargs)
    times = (datetime.datetime.now() - local_time).seconds
    funcname = wrapped.__name__
    print('运行 {} 函数消耗的时间为 {} 分 {} 秒'.format(
        funcname, times // 60, times % 60))
    # print('Run {} time is {} minutes {} seconds'.format(
    #     funcname, times // 60, times % 60))
    return ret

@universal
class People:
    # 定义基本属性
    name = ""
    age = 0

    # 初始化函数
    def __init__(self, name, age):
        self.name = name
        self.age = age 
    
    # 静态方法
    @universal
    @staticmethod
    def work():
        time.sleep(3)
        print("I could work")

    # 类方法
    @universal
    @classmethod
    def speak(cls, words):
        time.sleep(1)
        print(words)

    # 实例方法
    @universal
    def eat(self, food):
        time.sleep(5)
        print(f"I am eating {food}")
    
# 普通函数
@universal
def read(bookname):
    time.sleep(1)
    print(f"I am reading {bookname}")


# 调用普通函数
read("《Linux 二进制分析》")

# 调用静态方法
People.work()

# 调用类方法
People.speak("hello world")

## 调用实例方法
# 实例化一个对象
xiaoming = People(name="xiaoming", age=18)
xiaoming.eat("a sandwich")

运行后结果

图片

我们可以直观地看到, eat 这个函数运行时间最长,运行时间为 5 秒,可能需要我们针对性解决

如果你不想复制装饰器文件,可以直接从以下百度云链接中下载

https://pan.baidu.com/s/1mO9W2QGeJRp8qNjWzelUvw 提取码: ajp4

  「你即将失去如下所有学习变强机会」

学习效率低,学不到实战内容,花几千、上万报机构没有性价比

一顿自助钱,我承诺一定让用户满意,也希望用户能给予我一份信任

【详情下方图片了解】,【扫下方二维码加入】:只做高质量优质精品内容」

现在圈子已经有150+师傅相信并选择加入我们,人数满199人将涨价,老用户可永久享受初始加入价格,圈子内容持续更新中

图片

图片

免责声明

由于传播、利用本公众号所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,本公众号及作者不为此承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉。谢谢!

  • 22
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吉吉说安全

感谢打赏,交个朋友!有困难找我

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值