python中有装饰器一说, 普遍的装饰器是修饰函数的, 长这样:
def fn(f):
def func():
print('pre do any')
f()
print('after do any')
return func
@fn
def doAny():
print('do any')
# doAny = fn(doAny) 上面的@fn为装饰器的常用形式, 此处为装饰器的实际运行过程
doAny()
通过这样, 我们就可以实现一个普通的函数装饰器, 利用装饰器我们可以很方便的为函数扩展功能, 例如实现拦截功能,或者针对别人写的函数做一些扩展都是可以的。
而我们常见的其实还有一类装饰器, 那就是用于类的装饰器, 虽然形式大同小异, 但是还是有点点不同的
def decorator(n):
def func(fn):
print('pre do any')
fn.age = n
print('end do any')
# 可以看到类装饰器多了这么一句,实际上传入的fn为一个类, 所以需要确保你写的装饰器调用之后,仍然能返回一个类, 所以在这里要返回fn
return fn
return func
@decorator(25) # 这是类装饰器的常用形式, 例如@admin.register(Group),是不是很常见?
class Person:
def __init__(self, name):
self.name = name
# Person = decorator(3)(Person) # 这是类装饰器实际的调用过程, 很丑...
print(type(Person))
p = Person('will')
print(p.name, p.age)
通过上述代码, 我们可以看到修饰类的装饰器,在内部的函数中返回了fn, 这是因为修饰后的类必须保证依然是原类, 通过类装饰器我们可以在类上面挂载很多东西, 比如类方法, 类属性等等...通过上面的例子, 就给Person类挂载了age类属性。
需要注意的是, 因为在调用过程中传递的都是类, 所以扩展的属性都是类属性, 所以如果需要为类添加属性的时候才使用这种模式,为什么强调这点呢, 因为类属性是所有实例共有的...
上面只是个简单的例子, 实际上,你在真实的代码的时候是可以利用关键字传参的,之后再在内部函数中调用setattr轻松为类进行扩展。