装饰器类学习小结

news/2024/7/6 0:32:43

装饰器

装饰器的原理以及函数类型的装饰器在网上有很多描述,本文我就只讲我对于 将装饰器定义为类的理解。

要将装饰器定义为一个类,需要在类中声明__call____get__方法,例子如下:

from time import time

class ttl_property(object):
    def __init__(self, ttl=None):
       self.ttl = ttl

    def __call__(self, func):
       def wrapper(*args,**kw):
          if 'name' not in self.__dict__.keys():
             self.__dict__['name']=(func(*args,**kw),time())
          last=self.__dict__['name'][1]
          value=self.__dict__['name'][0]
          now=time()
          if now-last>self.ttl:
             value=func(*args,**kw)
             self.__dict__['name']=(value,now)
          return value
       return wrapper

    def __get__(self, instance, owner):
       if instance is None:
            return self
       else:
            return types.MethodType(self, instance)

    def __set__(self, instance, value):
       self.__dict__['name'] = (value, time())
from ttl_property import ttl_property

class Book(object):
    """
    >>> b = Book()
    >>> b.price
    80.0
    >>> b.price
    80.0
    >>> time.sleep(3)
    >>> b.price
    64.0
    >>> b.price
    64.0
    >>> time.sleep(3)
    >>> b.price
    51.2
    """

    def __init__(self):
        self._price = 100.0

    @ttl_property(ttl=2)
    def price(self):
        self._price = self._price * 0.8
        return self._price

这是我在一个网站上做的实验,在这个实验中需要定义一个装饰器类ttl_property来装饰Book类中的函数,__call__函数可以将类的调用和函数类似,具体请查询网上资料。

我要着重强调两点:

1:装饰器类中的__get__方法很重要,因为在装饰器中返回的函数并不是原本类中的函数,也就是说在原本类所对应的实例中,这个函数并不存在,所以如果没有__get__方法,那么调用就会出问题;那么types.MethodType(self, instance)就是将方法和实例绑定起来,这样在这个实例中就包含了这个方法,就可以顺利调用了。

2:如果在原来的方法中需要使用self,那么在装饰器返回的方法中也要包含self参数,不然就不行

转载于:https://blog.51cto.com/zhengdzy/2137203


http://www.niftyadmin.cn/n/4071058.html

相关文章

火雨_Nick

2019独角兽企业重金招聘Python工程师标准>>> https://blog.csdn.net/wp1603710463/article/details/50478404 所有的Spring Bean默认都是单例。当容器分配一个Bean时,它总返回Bean的同一个实例。为了让Spring在每次请求时都为Bean产生一个新的实例&#…

发布FPU详解的前6章翻译

原文是在masm32v9.0中找到的,相信已安装该开发包的朋友都知道,不过面对全英文的长篇大论,有些朋友是有喜有气,有力不从心的感觉。我为了在Win32asm中掌握FPU的使用,在网上搜索了一番,想找找有没有关于FPU的…

java 多线程中的 ThreadLocal 类与 volatile 修饰符

ThreadLocal(线程局部变量) 为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量。 volatile 修…

Win32汇编开发环境介绍和RadAsm简明教程第二版

自从第一版发布以来,陆续收到不少网友的来信,很多朋友说教程不错,很适合入门Win32汇编的开发环境,当初我写这个教程的目的也正是如此,所以自我感觉还不错。但随着来信的增多,问题也陆陆续续地来了&#xff…

SQL Server之看懂执行计划

在SQL Server中,选中一段SQL按CtrlL,就可以查看它的执行计划。 上面是一个执行计划的实例,在SQL Server中,执行计划是从右往左看的。 SQL Server中,查找数据的方式有以下几种: 1,表扫描&#xf…

猜数字游戏的bug讨论,如何发现并修正bug。

猜数字游戏的bug讨论,如何发现并修正bug。作者:jhkdiy之前大家都看过了《C++编写猜数字游戏》的文章了,整个源代码比较简单,有C++基础就可以看明白程序的流程,但我的目的…

精读《webpack4.0 升级指南》

本周精读的是 webpack4.0 一些变化,以及 typescript 该怎么做才能最大化利用 webpack4.0 的所有特性。 1 引言 前段时间尝试了 parcel 作为构建工具,就像农村人享受了都市的生活,就再也回不去了一样,发现无配置真是前端构建工具的…

DefToEqu源代码下载

http://jhkdiy.go3.icpcn.com/code/download/define2equ.rar 使用Win32Asm编程的过程中,经常要用到常数定义,如果是有资源的程序更是如此。自己当初编程时是先将要转换的C语言常数ID复制到程序的常数区.const中,然后再用查找替换功能去掉#def…