函数装饰器
基础装饰器
"""
每个装饰器完成一个独立的功能, 功能之间互相分离
可以装饰普通函数
也可以装饰类中的函数
"""
def wrap1(func):
def inner(*args, **kwargs):
print("wrap1 option")
r = func(*args, **kwargs)
return r
return inner
@wrap1
def sum(x, y):
return x+y
class Foo:
@wrap1
def sum(x, y):
return x+y
print(sum(1, 2))
print(Foo().sum(1, 2))
查看函数信息
from functools import wraps
def wrap2(func):
@wraps(func)
def inner(*args, **kwargs):
print("wrap2 option")
r = func(*args, **kwargs)
return r
return inner
@warp2
def sum(x, y):
"""
求和函数
"""
return x+y
print(func_a.__doc__)
装饰器带开关
"""
声明一个 tag, 在函数定义时传给装饰器
通常有两种用法
1. 用作总开关, 参数为变量, 因为当参数为变量时, 声明函数时即确定装饰器的参数, 并非调用前可改
2. 仅少量函数需要装饰器, 参数为定值
"""
from functools import wraps
wrap_tag = True
def wrap3(tag):
def outer(func):
@wraps(func)
def inner(*args, **kwargs):
print(tag)
if tag:
print("wrap3 option")
r = func(*args, **kwargs)
return r
return inner
return outer
@wrap3(wrap_tag)
def sum(x, y):
"""
求和函数
"""
return x+y
print(sum(1, 2))
wrap_tag = False
print(sum(1, 2))
类装饰器
装饰类中的函数
class Wrap:
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
print("执行装饰器代码")
r = lambda *args, **kwargs: self.func(instance, *args, **kwargs)
return r
class Foo:
@Wrap
def sum(self, x, y):
return x+y
print(Foo().sum(1, 2))
装饰普通函数
class Wrap:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("执行装饰器代码")
r = self.func(*args, **kwargs)
return r
@Wrap
def sum(x, y):
return x+y
print(sum(1, 2))
常用内置装饰器
property – 方法转属性
"""
类中方法的调用是 obj.funcName()
但有时候, 这样的使用并不符合"属性"和"方法"的使用习惯
例如: 直径属于圆的属性
我们使用它的时候, 用属性的方式更加合理
"""
class Circle:
def __init__(self, r):
self.r = r
@property
def d(self):
return self.r * 2
c = Circle(1)
print(c.d)
classmethod - 类绑定方法
class Foo:
@classmethod
def boo(cls):
print("我是 %s 类" % cls.__name__)
Foo.boo()
staticmethod - 类和对象都可以调用
class Foo:
@staticmethod
def check_err(err):
if err != None:
print(err)
Foo.check_err("输入有误")
f = Foo()
f.check_err("输入有误")
多个装饰器执行顺序
"""
多个装饰器同时装饰一个函数时, 按装饰先后顺序依次执行
并遵循先入后出的规则
所以下边示例的结果为:
1 start
2 start
func
2 end
1 end
"""
def wrapper1(func):
def inner(*args, **kwargs):
print("1, before")
func(*args, **kwargs)
print("1, end")
return inner
def wrapper2(func):
def inner(*args, **kwargs):
print("2, before")
func(*args, **kwargs)
print("2, end")
return inner
@wrapper1
@wrapper2
def funcA(x):
print(x)
funcA(100)