zoukankan      html  css  js  c++  java
  • python 装饰函数2

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    """
    Created on Tue May  5 21:40:49 2020
    
    @author: root
    
    装饰器语法糖
    装饰器的使用方法很固定:
    
    1.先定义一个装饰函数(帽子)(也可以用类、偏函数实现)
    2.再定义你的业务函数、或者类(人)
    3.最后把这顶帽子带在这个人头上
    
    
    案例:https://www.jb51.net/article/168276.htm
    """
    
    #2日志打印器
    # 首先是日志打印器。
    # 它要实现的功能是
    # 在函数执行前,先打印一行日志告知一下主人,我要执行函数了。
    # 在函数执行完,也不能拍拍屁股就走人了,咱可是有礼貌的代码,再打印一行日志告知下主人,我执行完啦。
    def logger(func):
        def wrapper(*args,**kwargs):
            print ('start--------------')
            func(*args,**kwargs)
            print ('end----------------')
        return wrapper    
    
    @logger
    def add(x,y):
        print('{} + {} = {}'.format(x, y, x+y))
        
    add(20,90) 
    
    
    #3 入门用法:时间计时器
    import time
    def timer(func):
        def wrapper(*args,**kw):
            t1=time.time()
            func(*args,**kw)
            t2=time.time()
            cost_time=t2-t1
            print ("花费时间:{}秒".format(cost_time))
        return wrapper        
            
    @timer
    def want_sleep(sleep_time):
        time.sleep(sleep_time)






    
    
    
    
    want_sleep(10)    
    
    
    
    
    
    # 3进阶用法:带参数的函数装饰器
    def say_hello(contry):
        def wrapper(func):
            def deco(*args,**kwargs):
                if contry=='china':
                    print ("ni hao")
                elif contry=='american':
                    print ('hello')
                else:
                    return
                func(*args,**kwargs)
            return deco
        return wrapper    
    
    
    @say_hello('american')
    def american():
        print ('----------------china')
    
    @say_hello('china')
    def chinese():
        print ('----------------zhongguo')
    
    
    american()
    print ('---------------')
    chinese()
    
    
    
    
    
    
    
    # 高阶用法:不带参数的类装饰器
    """
    以上都是基于函数实现的装饰器,在阅读别人代码时,还可以时常发现还有基于类实现的装饰器。
    基于类装饰器的实现,必须实现 __call__ 和 __init__两个内置函数。
    
    __init__ :接收被装饰函数
    __call__ :实现装饰逻辑
    """
    class logger(object):
        def __init__(self,func):
            self.func=func
        
        def __call__(self,*args,**kwargs):
            print("[INFO]: the function {func}() is running..."
            .format(func=self.func.__name__))
            return self.func(*args,**kwargs)    
    
    
    
    @logger
    def say(something):
        print ("say {}!".format(something))
    say('hello')
    
    
    
    #  高阶用法:带参数的类装饰器
    # 上面不带参数的例子,你发现没有,只能打印INFO级别的日志,正常情况下,我们还需要打印DEBUG WARNING等级别的日志。 这就需要给类装饰器传入参数,给这个函数指定级别了。
    # 带参数和不带参数的类装饰器有很大的不同。
    
    # __init__ :不再接收被装饰函数,而是接收传入参数。
    # __call__ :接收被装饰函数,实现装饰逻辑
    
    class logger2(object):
        def __init__(self,level='INFO'):
            self.level=level
            
            
        def __call__(self,func):
            def wrapper(*args,**kwargs):
                print("[{level}]: the function {func}() is running..."
                .format(level=self.level, func=func.__name__))
                func(*args, **kwargs)
            return wrapper
    
    
    @logger2(level='warning')
    def say(something):
        print ("say {}!".format(something))   
    say('hello')    
            
    
    
    
    
    
    
    # 内置装饰器:property
    # 以上,我们介绍的都是自定义的装饰器。
    # 其实Python语言本身也有一些装饰器。比如property这个内建装饰器,我们再熟悉不过了。
    # 它通常存在于类中,可以将一个函数定义成一个属性,属性的值就是该函数return的内容。
    
    class Student(object):
      def __init__(self, name):
        self.name = name
        self.name = None
     
      @property
      def age(self):
        return self._age
     
      @age.setter
      def age(self, value):
        if not isinstance(value, int):
          raise ValueError('输入不合法:年龄必须为数值!')
        if not 0 < value < 100:
          raise ValueError('输入不合法:年龄范围必须0-100')
        self._age=value
     
      @age.deleter
      def age(self):
        del self._age
     
    XiaoMing = Student("小明")
     
    # 设置属性
    XiaoMing.age = 25
    
    print (XiaoMing.name)
    print (XiaoMing.age)
    
    
    
    
    
    # example2:
    class Student:
        def __init__(self,name):
            self.name=name
        
        @property
        def math(self):
             return self._math
         
        @math.setter
        def math(self,value):
             if 0<=value<=100:
                self._math=value
             else:
                 raise ValueError("Valid value must be in [0, 100]")
             
             
             

    实现propetry 装饰器


    class TestProperty(object):
        def __init__(self, fget=None, fset=None, fdel=None, doc=None):
            self.fset = fset
            self.fget = fget
            self.fdel = fdel
            self.__doc__ = doc


        def __get__(self, obj, objtype=None):
            print('---in --get')
            if obj is None:
                return self
            if self.fget is None:
                raise AttributeError
            return self.fget(obj)

        def __set__(self,obj,value):
            print ('----in --set')
            if self.fset is None:
                raise AttributeError
            self.fset(obj,value)

        def __delete__(self,obj):
            print ('---in ---delete')
            if self.fdel is None:
               raise  AttributeError
            self.fdel(obj)

        def getter(self,fget):
            print ('in getter')
            return type(self)(fget,self.fset,self.fdel,self.__doc__)

        def setter(self,fset):
            print ('in setter')
            return type(self)(fset,self.fget,self.fdel,self.__doc__)
        
        def deleter(self,fdel):
            print ('in fdel')
            return type(self)(fdel,self.fget,self.fset,self.__doc__)

    测试一下:

    class Student:
      def __init__(self, name):
        self.name = name
     
      # 其实只有这里改变
      @TestProperty
      def math(self):
        return self._math
     
      @math.setter
      def math(self, value):
        if 0 <= value <= 100:
          self._math = value
        else:
          raise ValueError("Valid value must be in [0, 100]")
  • 相关阅读:
    伍佰《突然的自我》
    .NET常见ORM框架
    并发和压测工具
    底层源码调试工具
    c 冒泡排序
    c 指定范围的质数
    c 筛法列举质数
    c 牛顿法求方程近似解
    c 二分法求方程近似解
    css选择器 及其权重
  • 原文地址:https://www.cnblogs.com/1314520xh/p/12833640.html
Copyright © 2011-2022 走看看