装饰器

作者:管理员 发布时间:2021-01-29 17:26

装饰器就是增强函数或类的功能的一个函数。它可以装饰函数,也可以装饰类。

和包一样,Python有些内置包,你也可以自定义包。装饰器也有内置装饰器,也可以自定义装饰器。

装饰器经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。

内置装饰器

常见的内置装饰器有三种,@property、@staticmethod、@classmethod

@staticmethod

这应该是我们最常用的装饰器,标记类内的函数为静态方法。

静态方法,就是不需要对类进行实例化就能够使用的函数。

class A(object):
    @staticmethod
    def f():
        print('SuanFaShi');

class C(object):
    def f():
        print('AI');
 
A.f();          #被修饰器修饰后的方法,可直接使用
cobj = C()  #没有装饰的类内函数,需要实例化
cobj.f()        # 实例化后才能调用,否则报错


@property

把类内方法当成属性来使用,必须要有返回值,相当于getter;
假如没有定义 @func.setter 修饰方法的话,就是只读属性

class Car:

    def __init__(self, name, price):
        self._name = name
        self._price = price    
     
    @property
    def car_name(self):
        return self._name
        
     # car_name可以读写的属性   
     @car_name.setter
     def car_name(self, value):
         self._name = value
         
     # car_price是只读属性 
     @property
     def car_price(self):
         return str(self._price) + '万'
         
benz = Car('benz', 30)

print(benz.car_name)   # benz
benz.car_name = "baojun"
print(benz.car_name)   # baojun
print(benz.car_price)  # 30万


@classmethod

类方法,不需要self参数,但第一个参数需要是表示自身类的cls参数。

class Demo(object):

    text = "三种方法的比较"
    
    def instance_method(self):
        print("调用实例方法")

    @classmethod
    def class_method(cls):
        print("调用类方法")
        print("在类方法中 访问类属性 text: {}".format(cls.text))
        print("在类方法中 调用实例方法 instance_method: {}".format(cls().instance_method()))

    @staticmethod
    def static_method():
        print("调用静态方法")
        print("在静态方法中 访问类属性 text: {}".format(Demo.text))
        print("在静态方法中 调用实例方法 instance_method: {}".format(Demo().instance_method()))

if __name__ == "__main__":
    # 实例化对象
    d = Demo()
    
    # 对象可以访问 实例方法、类方法、静态方法
    # 通过对象访问text属性
    print(d.text)
    
    # 通过对象调用实例方法
    d.instance_method()
    
    # 通过对象调用类方法
    d.class_method()
    
    # 通过对象调用静态方法
    d.static_method()
    
    # 类可以访问类方法、静态方法
    # 通过类访问text属性
    print(Demo.text)
    
    # 通过类调用类方法
    Demo.class_method()
    
    # 通过类调用静态方法
    Demo.static_method()

@staticmethod 装饰的静态方法里面,想要访问类属性或调用实例方法,必须需要把类名写上;
而@classmethod装饰的类方法里面,会传一个cls参数,代表本类,这样就能够避免手写类名的硬编码。


自定义装饰器

Python中使用@表标记装饰器,我们可以写个函数,函数内写一些功能;

如,我们可以封装一个验证用户身份的修饰器,或debug日志的装饰器

def debug(func):      #把被修饰的函数传进来了
    def wrapper():
        print "[DEBUG]: enter {}()".format(func.__name__) #咱们中间开个小灶,写点自己的程序
        return func()      #把这个函数返回回去(只有这样这个函数才能运行,否则装不运行被修饰的函数)
    return wrapper   #这是装饰器的返回值

@debug                      #调用装饰器
def say_hello(): 
    print "hello!"

就是这么简单,但如果要修饰的函数,有参数,就要改下:

def debug(func):
    def wrapper(something):  # 指定一毛一样的参数
        print "[DEBUG]: enter {}()".format(func.__name__)
        return func(something)
    return wrapper  # 返回包装过函数

@debug
def say(something):
    print "hello {}!".format(something)

如果不确定有几个参数,咋办?

def debug(func):
    def wrapper(*args, **kwargs):  # 指定宇宙无敌参数
        print "[DEBUG]: enter {}()".format(func.__name__)
        print 'Prepare and say...',
        return func(*args, **kwargs)
    return wrapper  # 返回

@debug
def say(something):
    print "hello {}!".format(something)

你要说,不用修饰器,我直接在需要用的地方,写函数名不就行了!

答案是,随你喜欢。


标签:
Copyright © 2020 万物律动 旗下 AI算法狮 京ICP备20010037号-1
本站内容来源于网络开放内容的收集整理,并且仅供学习交流使用;
如有侵权,请联系删除相关内容;