0
点赞
收藏
分享

微信扫一扫

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]")

 

心有猛虎,细嗅蔷薇


举报

相关推荐

0 条评论