博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python--进阶处理9
阅读量:5243 次
发布时间:2019-06-14

本文共 3778 字,大约阅读时间需要 12 分钟。

 

# =========================第九章:元编程============================= # ----------------在函数上添加包装器----------------------- # 在函数上添加一个包装器,增加额外的操作处理(比如日志、计时等) import time from functools import wraps def timethis(func):     @wraps(func)     def wrapper(*args, **kwargs):         start = time.time()         result = func(*args, **kwargs)         end = time.time()         print(func.__name__, end - start)         return result     return wrapper @timethis def countdown(n):     while n > 0:         n -= 1 countdown(10000000) # 一个装饰器就是一个函数,它接受一个函数作为参数并返回一个新的函数 # 任何时候定义装饰器的时候,都应该使用functools 库中的@wraps 装饰器来注解底层包装函数 # 在编写装饰器的时候复制元信息是一个非常重要的部分。如果你忘记了使用@wraps,那么你会发现被装饰函数丢失了所有有用的信息 from functools import wraps import logging def logged(level, name=None, meaasge=None):     def decorate(func):         logname = name if name else func.__module__         log = logging.getLogger(logname)         logmsg = meaasge if meaasge else func.__name__         @wraps(func)         def wrapper(*args, **kwargs):             log.log(level, logmsg)             return func(*args, **kwargs)         return wrapper     return decorate @logged(logging.DEBUG) def add(x, y):     return x + y """ 最外层的函数logged()接受参数并将它们作用在内部的装饰器函数上面。 内层的函数decorate() 接受一个函数作为参数, 然后在函数上面放置一个包装器。 这里的关键点是包装器是可以使用传递给logged() 的参数的 """ from inspect import signature from functools import wraps def typeassert(*ty_args, **ty_kwargs):     def decorate(func):         if not __debug__:             return func         sig = signature(func)         bound_types = sig.bind_partial(*ty_args, **ty_kwargs).arguments         @wraps(func)         def wrapper(*args, **kwargs):             bound_values = sig.bind(*args, **kwargs)             for name, value in bound_values.arguments.items():                 if name in bound_types:                     if not isinstance(value, bound_types[name]):                         raise TypeError('Argument {} must be {}'.format(name, bound_types[name]))             return func(*args, **kwargs)         return wrapper     return decorate """ 可以看出这个装饰器非常灵活,既可以指定所有参数类型,也可以只指定部分。 并且可以通过位置或关键字来指定参数类型 """ @typeassert(int, z=int) def spam(x, y, z=24):     print(x, y, z) spam(1, 2, 3) spam(1, '2', 3) # spam(1, 'a', 'b') # ---------------------------------------------------------------------------------------------- # ------------------将装饰器定义为类的一部分-------------------------------- from functools import wraps class A:     # Decorator as an instance method     def decorator1(self, func):         @wraps(func)         def wrapper(*args, **kwargs):             print('Decorator 1')             return func(*args, **kwargs)         return wrapper     # Decorator as a class method     @classmethod     def decorator2(cls, func):         @wraps(func)         def wrapper(*args, **kwargs):             print('Decorator 2')             return func(*args, **kwargs)         return wrapper # 一个是实例调用,一个是类调用 a = A() @a.decorator1 def spam():     pass @A.decorator2 def grok():     pass # ----------------------------------------------------------------------- # 将装饰器定义为类 # 为了将装饰器定义成一个实例,你需要确保它实现了__call__() 和__get__() 方法 import types from functools import wraps class Profiled:     def __init__(self, func):         wraps(func)(self)         self.ncalls = 0     def __call__(self, *args, **kwargs):         self.ncalls += 1         return self.__wrapped__(*args, **kwargs)     def __get__(self, instance, cls):         if instance is None:             return self         else:             return types.MethodType(self, instance) @Profiled def add(x, y):     return x + y class Spam:     @Profiled     def bar(self, x):         print(self, x) # -------------------------------------------------------------------------------- # ?????????????????????????????332

转载于:https://www.cnblogs.com/fqfanqi/p/8446504.html

你可能感兴趣的文章
php表格输出
查看>>
长款或短款的处理(二)
查看>>
原来... 拷贝构造函数的参数为什么必须使用引用类型
查看>>
Effective C# 学习笔记(十一)尽量缩减函数体的大小,提高运行效率
查看>>
POJ1912 A highway and the seven dwarfs (判断凸包与直线相交 logn)
查看>>
71.lambda表达式的递归
查看>>
HTML 5 Canvas 代碼生成器
查看>>
SQL笔记
查看>>
高并发线程基础学习
查看>>
【使用DIV+CSS重写网站首页案例】CSS选择器
查看>>
字典对象的 Pythonic 用法(上篇)
查看>>
(Mysql)Navicat如何导出Excel格式表结构
查看>>
正则表达式
查看>>
Microsoft Visual Studio 常用快捷键总结
查看>>
c#判断一个时间的时间段
查看>>
MVC 数据库增删改查(2) 视图
查看>>
递归练习
查看>>
最小生成树(模板)
查看>>
Codeforces Round #486 (Div. 3) CD
查看>>
constructor C++ example
查看>>