博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python学习笔记--装饰器
阅读量:5026 次
发布时间:2019-06-12

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

Python学习笔记--装饰器

当你要提升自己颜值的时候该如何做? 可以整容,但是能不能在不修改本身器官下来提升颜值?

答案就是装饰器

def add(x,y):        print("I am working now")        return x+y
  • 你编写了一段程序,但是你觉得功能不够,例如你希望在运行add的时候,增加一段解释性的输出.就可以这样子.

    def deco(func):      print("The value is ")      return func      print(deco(add(3,9)))
  • 输出是

    I am working now
    The value is
    12

  • 这样就做到了在没有改写代码的情况下增加了功能.可能你觉得这个例子有点简单,我们在看一个复杂点的.


  • 需求1:在执行add()方法的时候增加类型检查.

    def requires_int(decorated):      def inner(*args,  **kwargs):          kwargs_value=[i for i in kwargs.values()]          for arg in list(args)+kwargs_value:              print(arg)              if not isinstance(arg,int):                  raise TypeError('%s only accepts integers as arguments'%decorated.__name__)          return decorated(*args,**kwargs)      return inner      def add(x,y):        """ Return the sum of x and y"""        return x+y      add=requires_int(add)      add('3',5)      TypeError: add only accepts integers as arguments
  • 但是有人疑问,写的太麻烦了,不如直接在代码上加一个类型检查. 但是如果再增加一个需求呢?


需求二:计算程序运行事件.

def addTime(decorated):              def inner(x,y):                  start=time.clock()                  decorated(x,y)                  end=time.clock()                  addTime=(end-start)*1000                  print("Time used",addTime)                  return decorated(x,y)              return inner              add=addTime(add)          Time used 0.03699999999999884
  • 如果再有新需求,再写一个装饰器就可以了.是不是很方便?

并且,两个装饰器还可以一起用.像这样

add=addTime(add)            add=requires_int(add)            add(4,8)

但是这样写感觉好麻烦,每次都要赋值一次,没关系,python为你专门准备了语法糖.其实可以这样写

@addTime          @requires_int          def add(x,y):              """ Return the sum of x and y"""              time.sleep(0.7)              return x+y

感觉有点眼熟,Django的login_required()不就是这样写的吗.不仅是这样,Flask的路由也是装饰器写的@route.

需要注意的是,如果多个装饰器,运行顺序是从下到上.

瞬间觉得装饰器好有用,不好好学习不行了.


让我们再来学习一个实例. 需求3如果我们要写一个注册表装饰器.#每次运行一个函数,都会有记录这个函数#.

registers=[]            def register(decorated):                registers.append(decorated)                return decorated            @register            def foo():                return 3            @register            def bar():                return 5            for i in registers:                print(i())

最后输出3,5. 但是有点问题是,我觉得应该不同的函数的register应该分开.这应该怎么办呢

答案是写一个装饰器类

class Register(object):              def __init__(self):                  self._functions=[]#定义一个列表来装被装饰的函数              def register(self,decorated):#装饰函数                  self._functions.append(decorated)                  return decorated              def run_all_function(self,  *args,  **kwargs):                  return_values=[]                  for func in self._functions:                          return_values.append(func(*args,  **kwargs))                  return return_values                  a=Register()                  b=Register()                  @a.register                  def foo(x=5):                      return x                  @b.register                  def bar(x=4):                      return x                  @a.register                  @b.register                  def baz(x=7):                      return x                  print(a.run_all_function())                  print(b.run_all_function())                  [5, 7]                  [4, 7]

这样就可以做到互相不影响,每一个register都是不同实例,数值不会混乱,是不是特别方便?

让我们总结一下今天的学习.

装饰器可以在不修改代码下增加功能             装饰器可以叠加             装饰器可以写成一个类

转载于:https://www.cnblogs.com/maxaimee/p/6526255.html

你可能感兴趣的文章
Java连接RabbitMQ之创建连接
查看>>
开户vim编程之--cscope支持
查看>>
python数据类型图解
查看>>
js获取标准北京时间
查看>>
DZ!NT论坛 3.6.711删除用户各种错解决方案
查看>>
C#微信登录-手机网站APP应用
查看>>
HTML5实践 -- iPhone Safari Viewport Scaling Bug
查看>>
1.4 - 数据类型/字符编码练习题
查看>>
JAVAWEB 一一 Hibernate(框架)
查看>>
函数式编程基础(F#,JS)
查看>>
IntelliJ IDEA使用教程
查看>>
将ASP.NET页面内的数据导出到Excel 或 Word中
查看>>
unity入门笔记
查看>>
html5的cavans
查看>>
闰年测试
查看>>
JSP笔记(一)
查看>>
Android工具HierarchyViewer 代码导读(1) -- 功能实现演示
查看>>
Java基础——多态
查看>>
python-Django与Nginx整合gunicorn模块
查看>>
Java--集合框架
查看>>