装饰器的定义:python
装饰器本质上就是一个python函数,它可让其它函数在不须要作任何代码改动的前提下增长额外的功能,装饰器的返回值也是一个函数对象。它常常用于有切面需求的场景中,好比-- >插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,咱们就能够抽离出大量与函数功能自己无关的雷同的代码而且能够重复使用。缓存
装饰器的做用:闭包
就是为已经存在的函数或者对象添加额外的功能app
装饰器的写法:函数
(无参装饰器) 性能
def wrapper(func): def inner(*args, **kwargs): print('in inner function') res = func(*args, **kwargs) return res return inner @wrapper def index(name): print('my name is %s' % name) index('william')
(有参装饰器):带参数的装饰器和类装饰器属于进阶的内容。在理解这些装饰器以前,最好对函数的闭包和装饰器的接口约定可以有必定的了解。测试
能够这么理解,当带参数的装饰器被打在某个函数上时,好比@outter('critical')时,它其实就是一个函数,会被立刻执行,只要这个它返回的结果是一个装饰器时,那就没有问题,再好好体会一下==this
def outter(level): def wrapper(func): def inner(*args, **kwargs): if level == 'info': print('in inner function') res = func(*args, **kwargs) return res else: print('level not enough') return inner return wrapper @outter('critical') def index(name): print('my name is %s' % name) index('william')
(基于类实现的装饰器):装饰器函数其实这样一个接口约束,它必须接受一个__call__对象做为参数,而后返回一个callable对象,在python中通常callable对象都是函数,可是也有例外的,只要某个对象从新加载了__call__()方法,那么这个对象就是callable的。spa
class Wrapper: def __init__(self): self.current_name = [] def __call__(self, func): def inner(*args, **kwargs): flag = True if self.current_name: print('当前用户已经登录了') res = func(*args, **kwargs) return res else: while flag: user_name = input('user_name:').strip() password = input('password:').strip() if user_name == 'william' and password == '123': print('登录成功...') res = func(*args, **kwargs) self.current_name.append(user_name) return res else: print('user_name or password error') return inner class Test: @Wrapper() def index(self, name): print('my name is %s' % name) t = Test() t.index('william')
像__call__这样先后都带下划线的方法在python中被称为内置方法,有时候也被称为魔法方法,从新加载这些魔法方法通常会改变对象的内部行为,可让一个类对象拥有被调用的行为。设计
class Test: def __call__(self): print('this is call') t = Test() t() # this is call
python内置的装饰器:
@staticmethod
将类中的方法设置为静态方法,就是在不须要建立实例对象的状况下,能够经过类名来进行直接引用,来达到将函数功能与实例解绑的效果。
class Test: @staticmethod def index(x, y): print('x + y = %s' % (x+y)) cls = Test() print('能够经过实例对象来引用') cls.index(1, 2) print('经过类名直接引用静态方法') Test.index(1, 2) ''' 能够经过实例对象来引用 x + y = 3 经过类名直接引用静态方法 x + y = 3 '''
@classmethod
类方法的第一个参数是一个类,是将类的自己做为操做的方法。类方法是被哪一个对象调用的,就传入哪一个类做为第一个参数进行操做。
class Car: car = 'audi' @classmethod def value(cls, category): print('%s is the %s' % (category, cls.car)) class Bmw(Car): car = 'Bmw' class Benz(Car): car = 'Benz' print('经过实例进行调用') b = Bmw() b.value('normal') print('直接用类名进行调用') Benz.value('NOnormal')
@property
使调用类中方法像引用类中的字段属性同样。被修饰的特性方法,内部能够实现处理逻辑,可是对外部提供统一的调用方式,遵循了统一的访问的原则。
class Test: name = 'test' def __init__(self, name): self.name = name @property def index(self): print('hello my name is %s' % self.name) cls = Test('file') print('经过实例来引用属性') print(cls.name) print('像引用属性同样调用@property修饰的方法') cls.index