上下文管理(为加法函数计时)

为加法函数计时

使用装饰器显示该函数的执行时长

使用上下文管理显示该函数的执行时长

装饰器实现

import time

import datetime

from functools import wraps

def logger(fn):

@wraps(fn) # wraps(fn)(wrapper)

def wrapper(*args, **kw):

start = datetime.datetime.now()

ret = fn(*args, **kw)

delta = (datetime.datetime.now() - start).total_seconds()

print(delta)

return ret

return wrapper

@logger

def add(x, y):

time.sleep(2)

return x + y

上下文实现

最简单实现

增加__call__用法

import time

import datetime

class TimeIt:

def __init__(self, fn):

self.fn = fn

def __enter__(self):

self.start = datetime.datetime.now()

return self

def __exit__(self, exc_type, exc_val, exc_tb):

self.delta = (datetime.datetime.now() - self.start).total_seconds()

print(self.delta)

def __call__(self, *args, **kwargs):

ret = self.fn(*args, **kwargs)

return ret

def add(x, y):

""" This is add"""

time.sleep(2)

return x + y

with TimeIt(add) as foo:

print(foo(3,4))

需要增加初始化方法,为下面__call__使用

__enter__方法返回self是为了,有了__call__方法以后,可以这样使用with TimeIt(add) as foo: foo(3,4)

因为有了__call__后,实例变成可调用,而foo就是实例化后的实例

TimeIt(add)是将add函数名作为形参传进去

改成装饰器

import time

import datetime

class TimeIt:

def __init__(self, fn):

self.fn = fn

def __enter__(self):

self.start = datetime.datetime.now()

return self

def __exit__(self, exc_type, exc_val, exc_tb):

self.delta = (datetime.datetime.now() - self.start).total_seconds()

print(self.delta)

def __call__(self, *args, **kwargs):

print('call')

ret = self.fn(*args, **kwargs)

return ret

@TimeIt # add = TimeIt(add)

def add(x, y):

""" This is add"""

time.sleep(2)

return x + y

# 上下文用法

# with TimeIt(add) as foo:

# print(foo(3,4))

print(add(5,6))

print(add.__doc__)

print(add.__dict__)

print(add.__name__)

装饰器用法很简单,直接在add函数上加个@TimeIt

这是由于@TimeIt等价于add = TimeIt(add),把add函数名作为实参传入到TimeIt类中

就相当于为add函数加了一个类封装的功能或属性

而这个时候,我们发现,用装饰器实现后,直接走的是__call__方法中的语句块,而上下文没有执行(因为没有用with..as语句)

也就是说,要么用with..as语句,要么用装饰器方法,这是两个方法

(用with..as语句执行装饰器方法,这样比较繁琐,重复计算,因题而异)

但是,如何解决文档字符串的问题,怎么把add函数的配置信息也弄过来(看__doc__和__dict__就可以知道)

解决文档字符串问题

方法1

把函数对象的文档字符串赋给类

class TimeIt:

def __init__(self, fn):

self.fn = fn

self.__doc__ = self.fn.__doc__

self.__name__ = self.fn.__name__

self.__dict__ = self.fn.__dict__

方法2

使用functools.wraps函数

最终完整版

import time

import datetime

from functools import wraps

class TimeIt:

"""This is Class"""

def __init__(self, fn):

self.fn = fn

# 把函数对象的文档字符串赋给类

# self.__doc__ = self.fn.__doc__

# self.__name__ = self.fn.__name__

# @wraps = wraps(fn)(wrapper)

wraps(fn)(self) # wraps用法

# def __enter__(self):

# self.start = datetime.datetime.now()

# return self

# def __exit__(self, exc_type, exc_val, exc_tb):

# self.delta = (datetime.datetime.now() - self.start).total_seconds()

# print(self.delta)

def __call__(self, *args, **kwargs):

print('call')

self.start = datetime.datetime.now()

ret = self.fn(*args, **kwargs)

delta = (datetime.datetime.now() - self.start).total_seconds()

print(delta)

return ret

@TimeIt # add = TimeIt(add)

def add(x, y):

""" This is add"""

time.sleep(2)

return x + y

# 上下文用法

# with TimeIt(add) as foo:

# print(foo(3,4))

print(add(5,6))

print(add.__doc__)

print(add.__dict__)

print(add.__name__)

print(type(add))

第15行的用法wraps(fn)(self)是根据这个@wraps = wraps(fn)(wrapper)来的

@wraps是带参装饰器,fn就是带参,wrapper是传入的实参

简单来说,@wraps = wraps(fn)(wrapper)就是把fn的配置信息赋值给wrapper

所以wraps(fn)(self)就是把fn的配置信息赋值给实例(self就是实例化后的实例)

本文来自投稿,不代表Linux运维部落立场,如若转载,请注明出处:http://www.178linux.com/88584

linux中的加法函数,上下文管理练习(为加法函数计时)相关推荐

  1. python上下文管理关键字_详解 Python 中的 with 与 上下文管理器

    with 这个关键字,对于每一学习Python的人,都不会陌生. 操作文本对象的时候,几乎所有的人都会让我们要用 with open ,这就是一个上下文管理的例子.你一定已经相当熟悉了,我就不再废话了 ...

  2. Linux中用户的简介与管理

    女主宣言 众所周知,linux是一个多用户.多任务的操作系统.那么linux是如何区分和认证用户的,系统对每个用户的授权是如何管理的,出现问题时是如何追朔每个用户在系统内的操作记录,这些就涉及到了li ...

  3. Linux 中的逻辑卷 LVM 管理完整初学者指南

    这是 Linux 中 LVM(逻辑卷管理)的完整初学者指南. 在本教程中,您将了解 LVM 的概念.它的组件以及为什么要使用它. 我不会仅限于理论上的解释,我还将展示在 Linux 中创建和管理 LV ...

  4. Linux中源码包的管理

    什么是开放源码,编译程序和可执行文件     开放源码:就是程序代码,写给人类看的程序语言,但机器不认识,所以无法执行:     编译程序:将程序代码转译成为机器看得懂的语言:     可执行文件:经 ...

  5. linux中的权限管理,Linux中的用户和权限管理

    Linux是多用户,多任务操作系统:多用户是指多个用户可以同时使用系统资源,而多任务指同时运行多个进程. 用户是能够获取系统资源的权限的集合,Linux通过用户实现资源分隔. 用户组是具有相同特征用户 ...

  6. Linux内核学习笔记——Linux中的用户组和权限管理(UID是什么?)

    目录 一.背景 进程权限 最小权限原则 二.linux系统安全模型 用户 用户组 用户和组的关系 安全上下文 进程的用户ID 函数setreuid和setregid 函数seteuid和setegid ...

  7. python实现可以被with上下文管理的类或函数

    开始之前先明确一下with机制 1.类包函数__ enter__()和__exit__()函数,即是可以被上下文管理的类 __enter__用来执行with时的方法,__exit__返回对象给with ...

  8. Linux中用户与组群管理

    Linux是一个多用户操作系统,可以多个用户同时使用同一计算机,不同的用户对相同的资源拥有不同的使用权限,将同一类的用户归于一个组群,可以利用组群权限来控制组群成员用户的权限. Linux中用户分为三 ...

  9. c++ getpid函数_C Linux中的getpid()和getppid()函数

    c++ getpid函数 If we are working on the processes, signals related programming using C language in Lin ...

最新文章

  1. [转]阿里巴巴数据库连接池 druid配置详解
  2. python二分法递归_python 【递归 及 二分法】
  3. Redis操作Key
  4. php上传手机文件到服务器,安卓上传文件至PHP服务器(示例代码)
  5. angular 渐进_如何创建具有Angular和无头CMS的渐进式Web应用程序
  6. 人大提出新模型,将Two Stage的Video Paragraph Captioning变成One Stage,性能却没下降...
  7. SqlServe零碎要点---sqlserver如何使用日期计算,DateTime类型的格式化以及语法格式等等。
  8. python 帮助教师_花10分钟写一个Python脚本,搞定了初中老师一下午的工作
  9. js获取地址栏url以及获取url参数
  10. IDEA——使用JSONObject时报错怎么办?
  11. MySQL Client/Server Protocol
  12. 怪物猎人世界pc服务器在哪个文件夹,关于PC怪物猎人世界拆包文件的一些问题...
  13. python int too large to convert to C long
  14. flex blazeds java_Flex使用Blazeds与Java交互及自定义对象转换详解
  15. 小程序的优势和劣势是什么?
  16. 删除IE浏览器input框自带的删除叉
  17. 具有深度沉浸能力的人更能有所成就
  18. 小程序步数解密php,微信小程序--获取微信运动步数的实例代码
  19. Docker基础介绍(二)
  20. 若依ruoyi-vue总结

热门文章

  1. git使用回滚,清除暂缓区,解决冲突(持续更新)
  2. Flask爱家租房--发布新房源(保存房屋基本信息)
  3. python 爬虫 包_python爬虫学习之路-抓包分析
  4. SQLAlchemy()分页器paginate方法
  5. 机器学习之EM算法的原理推导及相关知识总结
  6. java.lang.IllegalArgumentException: Does not contain a valid host:port authority: ignorethis
  7. 【C#学习笔记】使用C#中的Dispatcher
  8. mysql批量用trim限定_如何使用trim()并更新mysql中的所有行[复制]
  9. Master-Detail(主表明细),确认可以出货的SQL指令 -- Not Exists
  10. 使用export/import导出和导入docker容器